diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/galaxy.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/galaxy.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/galaxy.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/galaxy.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,30 @@ +--- +namespace: intel +name: appqos +version: 1.0.1 + +readme: README.md + +authors: + - Khawar Abbasi + - Wojciech Andralojc + - Tomasz Kantecki + +description: Collection with single role to deploy and stop AppQoS + +license: + - BSD-3-Clause + +tags: + - rdt + - appqos + - cacheqos + - pqos + - mba + - cat + - mbm + - cmt + - sstbf + - sstcp + +repository: https://github.com/intel/intel-cmt-cat/tree/master/appqos/ansible diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/playbooks/deploy.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/playbooks/deploy.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/playbooks/deploy.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/playbooks/deploy.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,39 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- name: Deploy AppQoS + hosts: compute + roles: + - role: intel.appqos.appqos + state: present diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/playbooks/inventory/hosts intel-cmt-cat-4.0/appqos/ansible/intel/appqos/playbooks/inventory/hosts --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/playbooks/inventory/hosts 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/playbooks/inventory/hosts 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,44 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +[compute] + +# These hostname must be resolvable from deployment host + +#compute01 +#compute02 + +# The above can also be specified as follows: +#compute01 ansible_python_interpreter=/usr/bin/python3 +#compute02 ansible_python_interpreter=/usr/bin/python3 + diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/playbooks/stop.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/playbooks/stop.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/playbooks/stop.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/playbooks/stop.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,39 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- name: Stop AppQoS + hosts: compute + roles: + - role: intel.appqos.appqos + state: stopped diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/README.md intel-cmt-cat-4.0/appqos/ansible/intel/appqos/README.md --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/README.md 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/README.md 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,121 @@ +# README for Ansible Collection - intel.appqos +April 2020 + +## CONTENTS +- Introduction +- AppQoS Overview +- Dependencies +- Configuration +- Role Variables +- Example Playbook +- Requirements +- Further Information +- Legal Disclaimer + +## INTRODUCTION +An Ansible Collection with single role that installs AppQoS, +an API for Intel(R) Resource Director Technology (RDT) +and Intel(R) Speed Select Technology (SST), +on RHEL/CentOS/Fedora and Debian/Ubuntu Linux distributions. + + +## APPQOS OVERVIEW +AppQoS is a proof-of-concept software created to demonstrate the use of +Intel(R) RDT and Intel(R) SST to improve Quality of Service (QoS) for +applications via partitioning system resources. + +More information can be found in AppQoS README file available at: +https://github.com/intel/intel-cmt-cat/tree/master/appqos/README + + +## DEPENDENCIES +Intel(R) RDT CAT and MBA configuration is done via "libpqos" library: +https://github.com/intel/intel-cmt-cat + +Intel(R) SST BF and CP configuration via external "Intel pwr" library: +https://github.com/intel/CommsPowerManagement + +More information can be found in AppQoS README file available at: +https://github.com/intel/intel-cmt-cat/tree/master/appqos/README + + +## CONFIGURATION +AppQoS supports pools of resources, i.e. Pools. In each Pool one or more +application can be deployed, where application is one or more PIDs. + +Cache Allocation, Memory Bandwidth Allocation (via CAT and MBA), +Base Frequency, Core Power (via SST BF and CP) and affinity are configured +by AppQoS on per core basis. + +All configurations are pre-defined in appqos.conf file which is +"Read-Only" by default. No runtime changes are saved in the configuration file. +However, user can make changes on runtime using REST API. + +Not every platform supports all mentioned technologies so, the default +configuration includes only minimum number of settings that would work across +most of the platforms. Users can make changes in the configuration file and +tune it for specific hardware platform. +Example Intel(R) Xeon(R) 2nd Generation SP is available in appqos.conf + +Apart from installing configuration files, this Ansible script also: +- Installs required packages and dependencies including libpqos +- Generates self-signed certificate for SSL/TLS i.e. appqos.key and appqos.crt +- Creates appqos configuration file with minimal resources (mentioned above) +- Start AppQoS in the background +- Stop/terminate AppQoS running in the background + + +## ROLE VARIABLES +All variables are stored in main.yml file under role's "default" directory. +Based on user needs it can be changed. + +"state" variable controls action of the role: +- "present" (default) to deploy +- "stopped" to stop AppQoS instance + + +## EXAMPLE PLAYBOOK +Playbook to deploy AppQoS: +``` +- name: Deploy AppQoS + hosts: compute + roles: + - role: intel.appqos.appqos + state: present +``` + +Playbook to stop AppQoS: +``` +- name: Stop AppQoS + hosts: compute + roles: + - role: intel.appqos.appqos + state: stopped +``` + +## REQUIREMENTS +- Python >= 3.6 +- Ansible* >= 2.5 +- msr-tools installed + + +## FURTHER INFORMATION +Intel(R) Resource Directory Technology: +https://www.intel.com/content/www/us/en/architecture-and-technology/resource-director-technology.html + +Intel(R) Speed Select - Base frequency (SST-BF): +https://github.com/intel/CommsPowerManagement/blob/master/sst_bf.md + +Intel(R) SST-BF configuration Python script: +https://github.com/intel/CommsPowerManagement/blob/master/sst_bf.py + + +## LEGAL DISCLAIMER +THIS SOFTWARE IS PROVIDED BY INTEL"AS IS". NO LICENSE, EXPRESS OR +IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS +ARE GRANTED THROUGH USE. EXCEPT AS PROVIDED IN INTEL'S TERMS AND +CONDITIONS OF SALE, 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. diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/defaults/main.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/defaults/main.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/defaults/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/defaults/main.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,76 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +# By default deploy AppQoS +state: present + +# RDT/AppQoS repo details +rdt_repo: https://github.com/intel/intel-cmt-cat +rdt_repo_version: master + +# Directory where RDT/AppQoS repo lands +appqos_path: /root/ansible/appqos_repo + +# Appqos directory +appqos_dir: "{{ appqos_path }}/appqos" + +# Appqos KEY file - private key +appqos_key_file: "{{ appqos_dir }}/appqos.key" + +# Appqos CRT file - certificate +appqos_crt_file: "{{ appqos_dir }}/appqos.crt" + +# Appqos CSR file +appqos_csr_file: "{{ appqos_dir }}/appqos.csr" + +# Appqos config file +appqos_conf_path: /tmp/appqos.conf + +# Appqos process regexp +appqos_proc_regexp: '^python.? \./appqos\.py' + +# Appqos config file content +appqos_conf_content: | + { + "apps": [], + "auth": { + "password": "password", + "username": "admin" + }, + "sstbf": { + "configured": false + }, + "pools": [], + "power_profiles_expert_mode": true + } diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/meta/main.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/meta/main.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/meta/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/meta/main.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,67 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +galaxy_info: + author: Khawar Abbasi, Wojciech Andralojc, Tomasz Kantecki + description: Deploys or stops AppQoS + company: Intel Corporation + + license: BSD-3-Clause + + min_ansible_version: 2.5.0 + + platforms: + - name: Fedora + versions: + - all + - name: Ubuntu + versions: + - all + - name: EL + versions: + - 7 + + galaxy_tags: + - rdt + - appqos + - cacheqos + - pqos + - mba + - cat + - mbm + - cmt + - sstbf + - sstcp + + dependencies: [] diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/clone_appqos_repo.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/clone_appqos_repo.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/clone_appqos_repo.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/clone_appqos_repo.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,42 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- import_tasks: install_git.yml + +- name: Clone AppQoS repo + git: + repo: "{{ rdt_repo }}" + version: "{{ rdt_repo_version }}" + dest: "{{ appqos_path }}" + update: "yes" diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/deploy_appqos.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/deploy_appqos.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/deploy_appqos.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/deploy_appqos.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,46 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +# tasks file for AppQoS deployment +- import_tasks: install_libpqos.yml + tags: libpqos + +- import_tasks: install_venv.yml + tags: appqos + +- import_tasks: generate_ssl_key_certs.yml + tags: appqos + +- import_tasks: start_appqos.yml + tags: appqos diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/generate_ssl_key_certs.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/generate_ssl_key_certs.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/generate_ssl_key_certs.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/generate_ssl_key_certs.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,66 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- import_tasks: install_python.yml + +- name: Install PyOpenSSL + pip: + name: ['PyOpenSSL'] + +- name: Creating Key + command: + cmd: openssl genrsa -out "{{ appqos_key_file }}" + creates: "{{ appqos_key_file }}" + +- name: Setting permissions on key + file: + path: "{{ appqos_key_file }}" + mode: 0600 + state: file + +- name: Generate CSR + openssl_csr: + path: "{{ appqos_csr_file }}" + privatekey_path: "{{ appqos_key_file }}" + common_name: + country_name: + email_address: + organization_name: + +- name: Generate a self signed certificate + openssl_certificate: + csr_path: "{{ appqos_csr_file }}" + path: "{{ appqos_crt_file }}" + privatekey_path: "{{ appqos_key_file }}" + provider: selfsigned diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_git.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_git.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_git.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_git.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,45 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- name: Install GIT - RedHat + yum: + name: git + state: present + when: ansible_os_family == 'RedHat' + +- name: Install GIT - Debian + apt: + name: git + state: present + when: ansible_os_family == 'Debian' diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_libpqos.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_libpqos.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_libpqos.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_libpqos.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,48 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- import_tasks: clone_appqos_repo.yml + +- name: Check that the libpqos installed + stat: + path: /usr/lib/libpqos.so + register: libpqos_check + +- name: Build and install libpqos + make: + chdir: "{{ appqos_path }}" + target: install + params: + PREFIX: /usr + when: not libpqos_check.stat.exists diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_pgrep.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_pgrep.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_pgrep.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_pgrep.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,45 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- name: Install pgrep - RedHat + yum: + name: procps + state: present + when: ansible_os_family == 'RedHat' + +- name: Install pgrep - Debian + apt: + name: procps + state: present + when: ansible_os_family == 'Debian' diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_python.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_python.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_python.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_python.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,45 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- name: Install python - Debian + apt: + name: python3 + state: present + when: ansible_os_family == 'Debian' + +- name: Install python - RedHat + yum: + name: python3 + state: present + when: ansible_os_family == 'RedHat' diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_venv.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_venv.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/install_venv.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/install_venv.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,45 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- import_tasks: clone_appqos_repo.yml +- import_tasks: install_python.yml + +- name: Install virtualenv + pip: + name: ['virtualenv'] + +- name: Making python3 virtualized env + make: + chdir: "{{ appqos_dir }}" + target: "env_{{ ansible_hostname }}" diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/is_appqos_running.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/is_appqos_running.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/is_appqos_running.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/is_appqos_running.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,44 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- import_tasks: install_pgrep.yml + +- name: Get number of AppQoS processes from remote host + changed_when: false + shell: pgrep -c -f "{{ appqos_proc_regexp }}" || true + register: running_processes_num + +- name: Set fact based on the result + set_fact: + appqos_running: "{{ running_processes_num.stdout|int != 0 }}" diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/main.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/main.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/main.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,40 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +# tasks file for AppQoS deployment +- include_tasks: deploy_appqos.yml + when: state == "present" + +- include_tasks: stop_appqos.yml + when: state == "stopped" diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/start_appqos.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/start_appqos.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/start_appqos.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/start_appqos.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,64 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- name: Load MSR + modprobe: + name: msr + state: present + +- name: Check that the appqos.conf exists + stat: + path: "{{ appqos_conf_path }}" + register: stat_result + +- name: Create appqos.conf file with minimal required configurations + copy: + dest: "{{ appqos_conf_path }}" + content: "{{ appqos_conf_content }}" + when: not stat_result.stat.exists + +- import_tasks: is_appqos_running.yml + +- name: Start AppQoS/REST API server in background + shell: > + cd "{{ appqos_dir }}"; + source env_$HOSTNAME/bin/activate && + nohup ./appqos.py -c /tmp/appqos.conf /dev/null 2>&1 & + args: + executable: /bin/bash + when: not appqos_running + +- name: Check is AppQoS actually running + command: pgrep -c -f "{{ appqos_proc_regexp }}" + when: not appqos_running diff -Nru intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/stop_appqos.yml intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/stop_appqos.yml --- intel-cmt-cat-3.2/appqos/ansible/intel/appqos/roles/appqos/tasks/stop_appqos.yml 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/ansible/intel/appqos/roles/appqos/tasks/stop_appqos.yml 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,39 @@ +################################################################################ +# BSD LICENSE +# +# Copyright(c) 2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +--- +- import_tasks: is_appqos_running.yml + +- name: Stop AppQoS processes + command: pkill -9 -f "{{ appqos_proc_regexp }}" + when: appqos_running diff -Nru intel-cmt-cat-3.2/appqos/appqos.py intel-cmt-cat-4.0/appqos/appqos.py --- intel-cmt-cat-3.2/appqos/appqos.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/appqos.py 2020-06-19 10:42:55.000000000 +0000 @@ -3,7 +3,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/cache_ops.py intel-cmt-cat-4.0/appqos/cache_ops.py --- intel-cmt-cat-3.2/appqos/cache_ops.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/cache_ops.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/caps.py intel-cmt-cat-4.0/appqos/caps.py --- intel-cmt-cat-3.2/appqos/caps.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/caps.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/common.py intel-cmt-cat-4.0/appqos/common.py --- intel-cmt-cat-3.2/appqos/common.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/common.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/config.py intel-cmt-cat-4.0/appqos/config.py --- intel-cmt-cat-3.2/appqos/config.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/config.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/log.py intel-cmt-cat-4.0/appqos/log.py --- intel-cmt-cat-3.2/appqos/log.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/log.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/Makefile intel-cmt-cat-4.0/appqos/Makefile --- intel-cmt-cat-3.2/appqos/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/pid_ops.py intel-cmt-cat-4.0/appqos/pid_ops.py --- intel-cmt-cat-3.2/appqos/pid_ops.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/pid_ops.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/power_common.py intel-cmt-cat-4.0/appqos/power_common.py --- intel-cmt-cat-3.2/appqos/power_common.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/power_common.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/power.py intel-cmt-cat-4.0/appqos/power.py --- intel-cmt-cat-3.2/appqos/power.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/power.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/pqos_api.py intel-cmt-cat-4.0/appqos/pqos_api.py --- intel-cmt-cat-3.2/appqos/pqos_api.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/pqos_api.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/.pylintrc intel-cmt-cat-4.0/appqos/.pylintrc --- intel-cmt-cat-3.2/appqos/.pylintrc 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/.pylintrc 2020-06-19 10:42:55.000000000 +0000 @@ -22,7 +22,7 @@ # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. -load-plugins= +load-plugins=caniusepython3.pylint_checker # Pickle collected data for later comparisons. persistent=yes diff -Nru intel-cmt-cat-3.2/appqos/README intel-cmt-cat-4.0/appqos/README --- intel-cmt-cat-3.2/appqos/README 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/README 2020-06-19 10:42:55.000000000 +0000 @@ -2,7 +2,7 @@ ================================================================================ README for AppQoS -August 2019 +December 2019 ================================================================================ CONTENTS @@ -22,16 +22,17 @@ ============ AppQoS is a proof-of-concept software created to demonstrate the use of -Intel(R) RDT technologies (CAT, MBA) and Intel(R) SST-BF to improve QoS for -applications via partitioning system resources. +Intel(R) RDT technologies (CAT, MBA) and Intel(R) SST technologies +Base Frequency (BF), Core Power (CP) to improve QoS for applications +via partitioning system resources. AppQoS allows to assign Apps to Pools with different resources. In current version each of the Pools (group of cores) has fixed amount of -cache and memory bandwidth allocated. Thanks to Intel(R) SST-BF support, +cache and memory bandwidth allocated. Thanks to Intel(R) SST BF and CP support, AppQoS allows the CPU to be deployed with an asymmetric core frequency configuration. Amount of resources allocated and cores frequency configuration could depend on Pool’s priority. Intel(R) RDT CAT and MBA configuration is done via "libpqos" library and -Intel(R) SST-BF configuration via external "Intel pwr" library. +Intel(R) SST BF and CP configuration via external "Intel pwr" library. AppQoS provides simple, local, REST API management interface secured with HTTPS and "Basic HTTP Auth". REST API management interface allows @@ -45,10 +46,13 @@ REQUIREMENTS AND INSTALLATION ============================= -AppQoS requires Linux kernel v4.20/v5.2 (for Intel(R) SST-BF) +AppQoS requires minimum Linux kernel v4.20 (for Intel(R) RDT L3 CAT and MBA) +however, for support of Intel(R) SST BF and CP Linux kernel v5.2 is required. AppQoS is a part of Intel(R) RDT Software Package, it is located in "appqos" directory. -AppQoS depends on the following Python modules and external components: + +AppQoS requires Python v3.x and depends on the following Python modules +and external components: - pqos (libqos Python wrapper) - flask - flask_httpauth @@ -56,6 +60,10 @@ - jsonschema - Intel pwr library (github.com, CommsPowerManagement) +NOTE: +All required dependencies are installed and AppQoS is executed in virtualenv +when started via "make run" command. + To install "pqos" module, clone "intel/intel-cmt-cat" repository or download source code from github (for more information about repository cloning or downloading source code, @@ -82,8 +90,8 @@ For hardware requirements please see "Hardware Support" section of mentioned README file. -To get and install "Intel pwr" library required to configure Intel(R) SST-BF -please follow instructions at: +To get and install "Intel pwr" library required to configure +Intel(R) SST BF and CP please follow instructions at: https://github.com/intel/CommsPowerManagement @@ -93,8 +101,9 @@ AppQoS supports Pools of Apps, each with defined cores, cache and memory bandwidth allocation. Each App describes a single app, with one or more PIDs. -Cache Allocation, Memory Bandwidth Allocation (via CAT and MBA), -affinity and SST-BF are configured by AppQoS on per core basis. +Cache Allocation, Memory Bandwidth Allocation (via CAT and MBA), Base Frequency, +Core Power (via SST BF and CP) and affinity are configured by AppQoS on per core +basis. NOTE: make sure that cores are isolated via "isolcpu=" kernel param. @@ -114,11 +123,14 @@ "apps": [{"id": 1, "name": "App1", "pids": [1979, 1980]}, {"id": 2, "cores": [4], "name": "App2", "pids": [1592, 1593, 1594]}, {"id": 3, "cores": [5], "name": "App3", "pids": [1576, 1577, 1578]}], -"pools": [{"id": 1, "cores": [1, 2, 3], "name": "HP", "mba": 100, "cbm": "0xFF0", "apps": [1]}, +"pools": [{"id": 1, "cores": [1, 2, 3], "name": "HP", "mba": 100, "cbm": "0xFF0", "apps": [1], "power_profile": 1}, {"id": 2, "cores": [4, 5, 6], "name": "MP", "mba": 50, "cbm": "0xC", "apps": [2, 3]}, {"id": 3, "cores": [7, 8, 9], "name": "LP", "mba": 10, "cbm": "0x3", "apps": []}], +"power_profiles": [{"id": 1, "min_freq": 2500, "max_freq": 2500, "epp": "performance", "name": "HP"}], "auth": {"username": "admin", "password": "password"}, -"sstbf": {"enabled": true} +"sstbf": {"configured": false}, +"power_profiles_expert_mode": false, +"power_profiles_verify": true } "apps" section, Apps being managed by App QoS. @@ -134,14 +146,31 @@ - "cbm" - Intel RDT CAT CacheWayBitmask assigned to Pool - "mba" - Intel RDT MBA rate [%] assigned to Pool - "cores" - cores being assigned to Pool + - "power_profile" - Power Profile ID to be applied on pool's cores + +"power_profiles" section, Power Profiles/SST-CP. + - "id" - Profile's ID + - "name" - Profiles's name + - "min_freq" - min. frequency [MHz] + - "max_freq" - max. frequency [MHz] + - "epp" - Energy Performance Preference "auth" section, REST API username and password. - "username" - username - "password" - password "sstbf" section, Intel(R) SST-BF configuration. - - "enabled" – SST-BF requested state + - "configured" – SST-BF requested state +NOTE: +"power profiles" are ignored when SST-BF is configured. + +Global options: + - "power_profiles_expert_mode" - make power profiles editable via REST API + (Default: False) + + - "power_profiles_verify" - Admission Control feature for config file content, + verifies Power Profiles and Pools configuration (Default: True) USAGE ===== @@ -161,6 +190,10 @@ sudo ./appqos.py -c /tmp/appqos.conf -V +NOTE: +All required dependencies are installed and AppQoS is executed in virtualenv +when started via "make run" command. + For more information about configuration file please see CONFIGURATION paragraph, for information about runtime configuration please see REST API paragraph. For more info please see Step-by-step. @@ -171,7 +204,10 @@ The REST API is a local (but can be easily modified to allow remote access), secured interface that allows the user to control AppQoS. -The REST API allows to add, remove or move App between Pools and to add or remove Pools. +The REST API allows to: + - add, remove or move App between Pools, + - add, remove or modify Pools, + - configure Intel(R) SST BF and CP technologies NOTE: None of configuration changes made via REST API are saved to configuration file. @@ -217,31 +253,54 @@ - DELETE /apps/{id} - delete app for given id + - GET /pools - get all/collection of pools +- POST /pools - create new pool + - GET /pools/{id} - get pool for given id +- PUT /pools/{id} - modify pool for given id + - DELETE /pools/{id} - delete empty pool for given id + +- GET /power_profiles - get all/collection of power profiles + +- POST /power_profiles - create new power profile + +- GET /power_profiles/{id} - get power profile for given id + +- PUT /power_profiles/{id} - modify power profile for given id + +- DELETE /power_profiles/{id} - delete power profile for given id + + - GET /stats - get stats + - GET /caps - get system capabilities Example response: - {"capabilities": ["cat","mba","sstbf"] + {"capabilities": ["cat","mba","sstbf","power"] } + - GET /caps/sstbf - get Intel(R) SST-BF details Example response: - {"enabled": true, + {"configured": true, "hp_cores": [2,...,88], "std_cores": [0,...,95] } +- PUT /caps/sstbf - configure Intel(R) SST-BF + Example request: + {"configured": true} + USAGE SCENARIO ============== -AppQoS, leveraging Intel(R) RDT (CAT, MBA) and SST-BF Technologies, +AppQoS, leveraging Intel(R) RDT (CAT, MBA) and SST (BF, CP) Technologies, is to be used prioritize and protect performance of high priority applications. Please see below for complete step-by-step guide to configure AppQoS to @@ -264,14 +323,18 @@ "username": "admin" }, "sstbf": { - "enabled": true + "configured": true }, "pools": [ - ] + ], + "power_profiles_expert_mode": true } -Empty config file with essential configuration only. -REST API Authentication details and SST-BF enabled. +Empty config file with essential configuration only: + - REST API Authentication details, + - SST-BF configuration + - option to enable Power Profile "Expert Mode" to allow us to + add power profiles via REST API AppQoS command line parameters (for more info please see USAGE paragraph) @@ -289,49 +352,54 @@ START APPQOS -# ./appqos.py -c /tmp/appqos.conf -V -2019-05-09 14:17:39,955 DEBUG Supported capabilities: -2019-05-09 14:17:39,955 DEBUG ['cat', 'mba', 'sstbf'] - * Serving Flask app "rest" (lazy loading) +sudo make run + +2019-12-04 17:49:48,403 INFO Supported capabilities: +2019-12-04 17:49:48,403 INFO ['cat', 'mba', 'sstbf', 'power'] + * Serving Flask app "rest.rest_server" (lazy loading) * Environment: production - WARNING: Do not use the development server in a production environment. + WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. - * Debug mode: on -2019-05-09 14:17:40,001 INFO * Running on https://0.0.0.0:5000/ (Press CTRL+C to quit) -2019-05-09 14:17:40,130 DEBUG Cores controlled: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 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, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95] -2019-05-09 14:17:40,130 DEBUG Pool: Default/0 Cores: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 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, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95], Apps: None -2019-05-09 14:17:40,130 INFO Configuring SST-BF -2019-05-09 14:17:40,214 INFO Configuring RDT -2019-05-09 14:17:40,232 INFO Configuration changed + * Debug mode: off +2019-12-04 17:49:48,436 INFO * Running on https://127.0.0.1:5000/ (Press CTRL+C to quit) +2019-12-04 17:49:48,590 INFO Configuring SST-BF +2019-12-04 17:49:48,889 INFO SST-BF enabled, configured. +2019-12-04 17:49:48,889 INFO SST-BF HP cores: [2, 10, 11, 12, 13, 14, 15, 16, 25, 34, 35, 36, 37, 38, 39, 40] +2019-12-04 17:49:48,889 INFO SST-BF STD cores: [0, 1, 3, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 41, 42, 43, 44, 45, 46, 47] +2019-12-04 17:49:49,173 INFO Power Profiles/EPP enabled, not configured, SST-BF is configured +2019-12-04 17:49:49,173 INFO Configuring RDT +2019-12-04 17:49:49,180 INFO Configuration changed, processing new config... VERIFY INITIAL CONFIGURATION List all Pools -curl https://localhost:5000/pools -X GET --user admin:password -k +curl https://localhost:5000/pools -X GET --user admin:password -k | jq -[ - { - "id": 0, - "mba": 100, - "cbm": 2047, - "name": "Default", - "cores": [ - 0, - 1, - 2, -. . . - 93, - 94, - 95 - ] - } + { + "id": 0, + "mba": 100, + "cbm": 2047, + "name": "Default", + "cores": [ + 0, + 1, + 2, + 3, +... + 43, + 44, + 45, + 46, + 47 + ] + } ] NOTE: "Default" pool automatically created (id=0). -Pool takes all cores (96), 100% of MBA and full CAT CBM (all cache ways). +Pool takes all cores (48), 100% of MBA and full CAT CBM (all cache ways). List all Apps -curl https://localhost:5000/apps -X GET --user admin:password -k +curl https://localhost:5000/apps -X GET --user admin:password -k | jq { "message": "No apps in config file" @@ -340,28 +408,73 @@ NOTE: No Apps defined. List capabilities -curl https://localhost:5000/caps -X GET --user admin:password -k +curl https://localhost:5000/caps -X GET --user admin:password -k | jq { "capabilities": [ "cat", "mba", - "sstbf" + "sstbf", + "power" ] } NOTE: Detected capabilities listed, -Intel(R) RDT CAT, MBA and Intel(R) SST-BF technologies supported. +Intel(R) RDT CAT, MBA and Intel(R) SST BF, CP technologies supported. List Intel(R) SST-BF details curl https://localhost:5000/caps/sstbf -X GET --user admin:password -k | jq -c -{"enabled":true, -"hp_cores":[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40,50,58,59,60,61,62,63,64,73,82,83,84,85,86,87,88], -"std_cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95]} +{"configured":true + "hp_cores": [2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40], + "std_cores": [0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47]} NOTE: SST-BF enabled (as per config file), list of HP and STD cores provided. +Verify frequencies settings + +sudo python3 -c $'import pwr\nprint("\tFreq.\tFreq.\\nCore#\tMin\tMax\tEPP")\nfor c in pwr.get_cores(): c.refresh_stats(); print("{}\t{}\t{}\t{}".format(c.core_id, c.min_freq, c.max_freq, c.epp))' + + Freq. Freq. +Core# Min Max EPP +0 2100 2100 balance_performance +1 2100 2100 balance_performance +2 2800 2800 balance_performance +3 2100 2100 balance_performance +... +45 2100 2100 balance_performance +46 2100 2100 balance_performance +47 2100 2100 balance_performance + +NOTE: HP cores' frequencies are set to 2800MHz, STD cores' to 2100MHz + + +Unconfigure SST-BF + +curl https://localhost:5000/caps/sstbf -X PUT --user admin:password -k -H "Content-Type: application/json" -d '{"configured": false}' + +{ + "message": "SST-BF caps modified" +} + +Verify frequencies settings + +sudo python3 -c $'import pwr\nprint("\tFreq.\tFreq.\\nCore#\tMin\tMax\tEPP")\nfor c in pwr.get_cores(): c.refresh_stats(); print("{}\t{}\t{}\t{}".format(c.core_id, c.min_freq, c.max_freq, c.epp))' + + Freq. Freq. +Core# Min Max EPP +0 2300 2300 balance_performance +1 2300 2300 balance_performance +2 2300 2300 balance_performance +3 2300 2300 balance_performance +... +45 2300 2300 balance_performance +46 2300 2300 balance_performance +47 2300 2300 balance_performance + +NOTE: HP and STD cores' frequencies are set to 2300MHz + + CREATE APPS Create multiple processes, list their PIDs and core affinity @@ -370,11 +483,11 @@ for n in {1..5}; do bash -c "sleep 1d &"; done for i in `pidof sleep`; do taskset -p -c $i; done -pid 13894's current affinity list: 0-95 -pid 13892's current affinity list: 0-95 -pid 13890's current affinity list: 0-95 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13894's current affinity list: 0-47 +pid 13892's current affinity list: 0-47 +pid 13890's current affinity list: 0-47 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 Create App, specify cores @@ -412,9 +525,9 @@ for i in `pidof sleep`; do taskset -p -c $i; done pid 13894's current affinity list: 0-3 pid 13892's current affinity list: 0-3 -pid 13890's current affinity list: 0-95 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13890's current affinity list: 0-47 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 Create App, specify destination Pool ID @@ -444,22 +557,22 @@ for i in `pidof sleep`; do taskset -p -c $i; done pid 13894's current affinity list: 0-3 pid 13892's current affinity list: 0-3 -pid 13890's current affinity list: 0-95 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13890's current affinity list: 0-47 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 -NOTE: App2 PID’s core affinity is 0-95 as those are "Default" pool cores. +NOTE: App2 PID’s core affinity is 0-47 as those are "Default" pool cores. MODIFY "DEFAULT" POOL List SST-BF’s STD cores curl https://localhost:5000/caps/sstbf -X GET --user admin:password -k | jq .std_cores -c - [0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95] + [0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47] Modify "Default" pool to exclude HP cores, assign 50% of MBA and 4 LLC CWs (CBM: 0xF/15) -curl https://localhost:5000/pools/0 -X PUT --user admin:password -k -H "Content-Type: application/json" -d '{"cores": [0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95], "mba": 50, "cbm": "0xf"}' +curl https://localhost:5000/pools/0 -X PUT --user admin:password -k -H "Content-Type: application/json" -d '{"cores": [0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47], "mba": 50, "cbm": "0xf"}' "POOL 0 updated" @@ -471,7 +584,7 @@ "mba":50, "cbm":15, "name":"Default", -"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95], +"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47], "apps":[1,2]} Check how does "Default" pool modification has affected Apps in that pool @@ -500,11 +613,11 @@ for i in `pidof sleep`; do taskset -p -c $i; done -pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13890's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13890's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 NOTE: As some of the cores that were specified for APP1 are not part of "Default" pool anymore, core affinity for APP1 PIDs’ was reset to @@ -515,11 +628,11 @@ Get list of HP cores curl https://localhost:5000/caps/sstbf -X GET --user admin:password -k | jq .hp_cores –c -[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40,50,58,59,60,61,62,63,64,73,82,83,84,85,86,87,88] +[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40] Create HP Pool, with 7 (isolated) LLC CWs allocated and 100% of MBA -curl https://localhost:5000/pools -X POST --user admin:password -k -H "Content-Type: application/json" -d '{"name": "HP", "cores": [2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40,50,58,59,60,61,62,63,64,73,82,83,84,85,86,87,88], "cbm": "0x7F0", "mba": 100}' +curl https://localhost:5000/pools -X POST --user admin:password -k -H "Content-Type: application/json" -d '{"name": "HP", "cores": [2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40], "cbm": "0x7F0", "mba": 100}' { "id": 7 @@ -535,14 +648,101 @@ "mba":50, "cbm":15, "name":"Default", -"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95], +"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47], "apps":[1,2]}, {"name":"HP", -"cores":[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40,50,58,59,60,61,62,63,64,73,82,83,84,85,86,87,88], +"cores":[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40], "cbm":2032, "mba":100, "id":7}] +DEFINE AND APPLY POWER PROFILES + +Define HP power profile + +curl https://localhost:5000/power_profiles -X POST --user admin:password -k -H "Content-Type: application/json" -d '{"name": "PP HP", "min_freq": 3000, "max_freq": 3000, "epp": "performance"}' + +{ + "id": 0, + "message": "New POWER PROFILE 0 added" +} + +Define STD power profile + +curl https://localhost:5000/power_profiles -X POST --user admin:password -k -H "Content-Type: application/json" -d '{"name": "PP STD", "min_freq": 1500, "max_freq": 1500, "epp": "power"}' + +{ + "id": 1, + "message": "New POWER PROFILE 1 added" +} + +Get All Power Profiles to verify creation of new Power Profiles + +curl https://localhost:5000/power_profiles -X GET --user admin:password -k | jq + +[ + { + "name": "PP HP", + "min_freq": 3000, + "max_freq": 3000, + "epp": "performance", + "id": 0 + }, + { + "name": "PP STD", + "min_freq": 1500, + "max_freq": 1500, + "epp": "power", + "id": 1 + } +] + +Apply power profiles + +curl https://localhost:5000/pools/7 -X PUT --user admin:password -k -H "Content-Type: application/json" -d '{"power_profile": 0}' + +{ + "message": "POOL 7 not updated, Power Profiles configuration would cause CPU to be oversubscribed." +} + +NOTE: +AppQoS supports Admission Control feature, which protects CPU from being oversubscribed, +as a result of that, order in which power profile are applied is important. +(Configuration change can be forced by setting "verify" flag to "false" for a request) + +Lets apply the STD power profile first. + +curl https://localhost:5000/pools/0 -X PUT --user admin:password -k -H "Content-Type: application/json" -d '{"power_profile": 1}' + +{ + "message": "POOL 0 updated" +} + +curl https://localhost:5000/pools/7 -X PUT --user admin:password -k -H "Content-Type: application/json" -d '{"power_profile": 0}' + +{ + "message": "POOL 7 updated" +} + +Verify power profiles configuration in HW + +sudo python3 -c $'import pwr\nprint("\tFreq.\tFreq.\\nCore#\tMin\tMax\tEPP")\nfor c in pwr.get_cores(): c.refresh_stats(); print("{}\t{}\t{}\t{}".format(c.core_id, c.min_freq, c.max_freq, c.epp))' + + Freq. Freq. +Core# Min Max EPP +0 1500 1500 power +1 1500 1500 power +2 3000 3000 performance +3 1500 1500 power +... +45 1500 1500 power +46 1500 1500 power +47 1500 1500 power + +NOTE: +Cores from HP pool have frequency fixed to 3000MHz and EPP set to "performance", +STD pool's cores have frequency fixed to 1500MHz and EPP set to "power". + MOVE APP#2 Move App#2 to HP Pool(#7) @@ -583,10 +783,10 @@ "mba":50, "cbm":15, "name":"Default", -"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95], +"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47], "apps":[1]}, {"name":"HP", -"cores":[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40,50,58,59,60,61,62,63,64,73,82,83,84,85,86,87,88], +"cores":[2,10,11,12,13,14,15,16,25,34,35,36,37,38,39,40], "cbm":2032, "mba":100, "id":7, @@ -596,11 +796,11 @@ for i in `pidof sleep`; do taskset -p -c $i; done -pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13890's current affinity list: 2,10-16,25,34-40,50,58-64,73,82-88 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13890's current affinity list: 2,10-16,25,34-40 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 MODIFY APP#2 @@ -632,11 +832,11 @@ for i in `pidof sleep`; do taskset -p -c $i; done -pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 +pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-47 pid 13890's current affinity list: 2,11,13 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 REMOVE APP#2 @@ -674,11 +874,11 @@ Verify new configuration, check core affinity for i in `pidof sleep`; do taskset -p -c $i; done -pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13890's current affinity list: 0,1,3-9,17-24,26-33,41-49,51-57,65-72,74-81,89-95 -pid 13888's current affinity list: 0-95 -pid 13886's current affinity list: 0-95 +pid 13894's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13892's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13890's current affinity list: 0,1,3-9,17-24,26-33,41-47 +pid 13888's current affinity list: 0-47 +pid 13886's current affinity list: 0-47 NOTE: App#2’s PID core affinity set to "Default" pool cores @@ -706,7 +906,7 @@ "mba":50, "cbm":15, "name":"Default", -"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,74,75,76,77,78,79,80,81,89,90,91,92,93,94,95], +"cores":[0,1,3,4,5,6,7,8,9,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,33,41,42,43,44,45,46,47], "apps":[1]}] NOTE: No Pool#7 listed @@ -735,7 +935,7 @@ "mba":100, "cbm":2047, "name":"Default", -"cores":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,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,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95]}] +"cores":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,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,40,41,42,43,44,45,46,47]}] NOTE: "Default" pool reconfigured, takes all cores (96), 100% of MBA and full CAT CBM (all cache ways). diff -Nru intel-cmt-cat-3.2/appqos/requirements.txt intel-cmt-cat-4.0/appqos/requirements.txt --- intel-cmt-cat-3.2/appqos/requirements.txt 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/requirements.txt 2020-06-19 10:42:55.000000000 +0000 @@ -11,3 +11,4 @@ pytest-cov mock git+https://github.com/intel/CommsPowerManagement.git@pwr-v0.2.1#egg=pwr&subdirectory=pwr +caniusepython3 diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_app.py intel-cmt-cat-4.0/appqos/rest/rest_app.py --- intel-cmt-cat-3.2/appqos/rest/rest_app.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_app.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_auth.py intel-cmt-cat-4.0/appqos/rest/rest_auth.py --- intel-cmt-cat-3.2/appqos/rest/rest_auth.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_auth.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_exceptions.py intel-cmt-cat-4.0/appqos/rest/rest_exceptions.py --- intel-cmt-cat-3.2/appqos/rest/rest_exceptions.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_exceptions.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_misc.py intel-cmt-cat-4.0/appqos/rest/rest_misc.py --- intel-cmt-cat-3.2/appqos/rest/rest_misc.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_misc.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_pool.py intel-cmt-cat-4.0/appqos/rest/rest_pool.py --- intel-cmt-cat-3.2/appqos/rest/rest_pool.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_pool.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_power.py intel-cmt-cat-4.0/appqos/rest/rest_power.py --- intel-cmt-cat-3.2/appqos/rest/rest_power.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_power.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/rest/rest_server.py intel-cmt-cat-4.0/appqos/rest/rest_server.py --- intel-cmt-cat-3.2/appqos/rest/rest_server.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/rest/rest_server.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/sstbf.py intel-cmt-cat-4.0/appqos/sstbf.py --- intel-cmt-cat-3.2/appqos/sstbf.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/sstbf.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/stats.py intel-cmt-cat-4.0/appqos/stats.py --- intel-cmt-cat-3.2/appqos/stats.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/stats.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/rest_common.py intel-cmt-cat-4.0/appqos/tests/rest_common.py --- intel-cmt-cat-3.2/appqos/tests/rest_common.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/rest_common.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_cache_ops.py intel-cmt-cat-4.0/appqos/tests/test_cache_ops.py --- intel-cmt-cat-3.2/appqos/tests/test_cache_ops.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_cache_ops.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_caps.py intel-cmt-cat-4.0/appqos/tests/test_caps.py --- intel-cmt-cat-3.2/appqos/tests/test_caps.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_caps.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_config.py intel-cmt-cat-4.0/appqos/tests/test_config.py --- intel-cmt-cat-3.2/appqos/tests/test_config.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_config.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_pid_ops.py intel-cmt-cat-4.0/appqos/tests/test_pid_ops.py --- intel-cmt-cat-3.2/appqos/tests/test_pid_ops.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_pid_ops.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_power.py intel-cmt-cat-4.0/appqos/tests/test_power.py --- intel-cmt-cat-3.2/appqos/tests/test_power.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_power.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_pqos_api.py intel-cmt-cat-4.0/appqos/tests/test_pqos_api.py --- intel-cmt-cat-3.2/appqos/tests/test_pqos_api.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_pqos_api.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_app.py intel-cmt-cat-4.0/appqos/tests/test_rest_app.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_app.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_app.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_auth.py intel-cmt-cat-4.0/appqos/tests/test_rest_auth.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_auth.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_auth.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_caps.py intel-cmt-cat-4.0/appqos/tests/test_rest_caps.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_caps.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_caps.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_pool.py intel-cmt-cat-4.0/appqos/tests/test_rest_pool.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_pool.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_pool.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_power.py intel-cmt-cat-4.0/appqos/tests/test_rest_power.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_power.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_power.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_reset.py intel-cmt-cat-4.0/appqos/tests/test_rest_reset.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_reset.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_reset.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_sstbf.py intel-cmt-cat-4.0/appqos/tests/test_rest_sstbf.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_sstbf.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_sstbf.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_rest_stats.py intel-cmt-cat-4.0/appqos/tests/test_rest_stats.py --- intel-cmt-cat-3.2/appqos/tests/test_rest_stats.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_rest_stats.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_sstbf.py intel-cmt-cat-4.0/appqos/tests/test_sstbf.py --- intel-cmt-cat-3.2/appqos/tests/test_sstbf.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_sstbf.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/appqos/tests/test_stats.py intel-cmt-cat-4.0/appqos/tests/test_stats.py --- intel-cmt-cat-3.2/appqos/tests/test_stats.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/appqos/tests/test_stats.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2018 Intel Corporation. All rights reserved. +# Copyright(c) 2018-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/ChangeLog intel-cmt-cat-4.0/ChangeLog --- intel-cmt-cat-3.2/ChangeLog 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/ChangeLog 2020-06-19 10:42:55.000000000 +0000 @@ -1,4 +1,31 @@ ======================================================================== +Release v4.0.0 2020-06-26 +======================================================================= + +Contributors (alphabetical order): + Adrian Boczkowski + Babu Moger + Colin Ian King + Khawar Abbasi + Michal Aleksinski + Wojciech Andralojc + Xiaochen Shen + +1. Library: + - Use perf for IPC and cache misses monitoring with MSR interface + - Detection of MBA2.0 and MBA3.0 + - 32b MBM counters support + - AMD support +2. AppQoS: + - Added ansible scripts +3. PQoS: + - Added option to display MBT column in monitoring output + - Added option to disable IPC monitoring + - Added option to disable cache misses monitoring +4. General: + - Bug fixes + +======================================================================== Release v3.2.0 2019-12-20 ======================================================================= @@ -16,7 +43,6 @@ 2. General - Bug fixes - ======================================================================== Release v3.1 2019-08-16 ======================================================================= @@ -57,7 +83,6 @@ 1. General - Bug fixes - ======================================================================= Release v3.0 2019-02-14 ======================================================================= diff -Nru intel-cmt-cat-3.2/.clang-format intel-cmt-cat-4.0/.clang-format --- intel-cmt-cat-3.2/.clang-format 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/.clang-format 2020-06-19 10:42:55.000000000 +0000 @@ -6,12 +6,14 @@ AllowShortIfStatementsOnASingleLine: false IndentCaseLabels: false UseTab: Never -#AlignConsecutiveMacros: true +AlignConsecutiveMacros: true AlignTrailingComments: true AlwaysBreakAfterReturnType: AllDefinitions SortIncludes: false BreakBeforeInheritanceComma: true AllowAllParametersOfDeclarationOnNextLine: false BinPackParameters: false +BinPackArguments: true ReflowComments: true SpaceAfterCStyleCast: false +ColumnLimit: 80 diff -Nru intel-cmt-cat-3.2/debian/changelog intel-cmt-cat-4.0/debian/changelog --- intel-cmt-cat-3.2/debian/changelog 2020-04-17 11:23:32.000000000 +0000 +++ intel-cmt-cat-4.0/debian/changelog 2020-06-30 08:06:23.000000000 +0000 @@ -1,3 +1,10 @@ +intel-cmt-cat (4.0-1) unstable; urgency=medium + + * Sync with upstream 4.0 + - drop debian/compat, use debhelper-compat (=13) + + -- Colin King Tue, 30 Jun 2020 09:06:23 +0100 + intel-cmt-cat (3.2-2) unstable; urgency=medium * Fix gcc-10 build issue (Closes: #957361) diff -Nru intel-cmt-cat-3.2/debian/compat intel-cmt-cat-4.0/debian/compat --- intel-cmt-cat-3.2/debian/compat 2019-08-12 18:58:10.000000000 +0000 +++ intel-cmt-cat-4.0/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -12 diff -Nru intel-cmt-cat-3.2/debian/control intel-cmt-cat-4.0/debian/control --- intel-cmt-cat-3.2/debian/control 2020-04-17 11:21:43.000000000 +0000 +++ intel-cmt-cat-4.0/debian/control 2020-06-30 08:06:23.000000000 +0000 @@ -1,10 +1,11 @@ Source: intel-cmt-cat +Rules-Requires-Root: no Section: admin Priority: optional Maintainer: Colin King Uploaders: Kamal Mostafa Standards-Version: 4.1.2 -Build-Depends: debhelper (>= 12), quilt +Build-Depends: debhelper (>= 13), debhelper-compat (=13), quilt Homepage: https://github.com/01org/intel-cmt-cat Package: intel-cmt-cat diff -Nru intel-cmt-cat-3.2/debian/intel-cmt-cat.install intel-cmt-cat-4.0/debian/intel-cmt-cat.install --- intel-cmt-cat-3.2/debian/intel-cmt-cat.install 2019-02-19 16:51:23.000000000 +0000 +++ intel-cmt-cat-4.0/debian/intel-cmt-cat.install 2020-06-30 08:06:23.000000000 +0000 @@ -18,3 +18,11 @@ examples/perl/hello_world.pl usr/share/intel-cmt-cat/examples/perl examples/perl/Makefile usr/share/intel-cmt-cat/examples/perl examples/perl/README usr/share/intel-cmt-cat/examples/perl +examples/python/association.py usr/share/intel-cmt-cat/examples/python +examples/python/l2ca.py usr/share/intel-cmt-cat/examples/python +examples/python/l3ca.py usr/share/intel-cmt-cat/examples/python +examples/python/Makefile usr/share/intel-cmt-cat/examples/python +examples/python/mba.py usr/share/intel-cmt-cat/examples/python +examples/python/monitoring.py usr/share/intel-cmt-cat/examples/python +examples/python/README usr/share/intel-cmt-cat/examples/python +examples/python/reset_allocation.py usr/share/intel-cmt-cat/examples/python diff -Nru intel-cmt-cat-3.2/debian/intel-cmt-cat.lintian-overrides intel-cmt-cat-4.0/debian/intel-cmt-cat.lintian-overrides --- intel-cmt-cat-3.2/debian/intel-cmt-cat.lintian-overrides 2019-08-16 13:57:26.000000000 +0000 +++ intel-cmt-cat-4.0/debian/intel-cmt-cat.lintian-overrides 2020-06-30 08:06:23.000000000 +0000 @@ -1,2 +1,3 @@ -intel-cmt-cat: non-dev-pkg-with-shlib-symlink intel-cmt-cat: package-name-doesnt-match-sonames +intel-cmt-cat: executable-not-elf-or-script +intel-cmt-cat: link-to-shared-library-in-wrong-package diff -Nru intel-cmt-cat-3.2/debian/patches/0003-rdtset-Fixed-compilation-issue-with-gcc-10.patch intel-cmt-cat-4.0/debian/patches/0003-rdtset-Fixed-compilation-issue-with-gcc-10.patch --- intel-cmt-cat-3.2/debian/patches/0003-rdtset-Fixed-compilation-issue-with-gcc-10.patch 2020-04-17 11:20:37.000000000 +0000 +++ intel-cmt-cat-4.0/debian/patches/0003-rdtset-Fixed-compilation-issue-with-gcc-10.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -From 73d631f66b39471ccc07918403bde14222f8e006 Mon Sep 17 00:00:00 2001 -From: "Aleksinski, MichalX" -Date: Sun, 16 Feb 2020 22:47:54 -0800 -Subject: [PATCH] rdtset: Fixed compilation issue with gcc-10 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: 8bit - ---- - rdtset/common.c | 2 ++ - rdtset/common.h | 2 +- - 2 files changed, 3 insertions(+), 1 deletion(-) - -Index: intel-cmt-cat-3.2/rdtset/common.c -=================================================================== ---- intel-cmt-cat-3.2.orig/rdtset/common.c -+++ intel-cmt-cat-3.2/rdtset/common.c -@@ -41,6 +41,8 @@ - #include "common.h" - #include "rdt.h" - -+struct rdtset g_cfg; -+ - int - str_to_cpuset(const char *cpustr, const unsigned cpustr_len, cpu_set_t *cpuset) - { -Index: intel-cmt-cat-3.2/rdtset/common.h -=================================================================== ---- intel-cmt-cat-3.2.orig/rdtset/common.h -+++ intel-cmt-cat-3.2/rdtset/common.h -@@ -171,7 +171,7 @@ struct rdtset { - enum pqos_interface interface; /**< pqos interface to use */ - }; - --struct rdtset g_cfg; -+extern struct rdtset g_cfg; - - #define DBG(...) \ - do { \ diff -Nru intel-cmt-cat-3.2/debian/patches/series intel-cmt-cat-4.0/debian/patches/series --- intel-cmt-cat-3.2/debian/patches/series 2020-04-17 11:20:24.000000000 +0000 +++ intel-cmt-cat-4.0/debian/patches/series 2020-06-30 08:06:23.000000000 +0000 @@ -1,3 +1,2 @@ 0001-alter-install-paths.patch 0002-remove-build-and-install-of-examples.patch -0003-rdtset-Fixed-compilation-issue-with-gcc-10.patch diff -Nru intel-cmt-cat-3.2/examples/c/CAT_MBA/allocation_app_l2cat.c intel-cmt-cat-4.0/examples/c/CAT_MBA/allocation_app_l2cat.c --- intel-cmt-cat-3.2/examples/c/CAT_MBA/allocation_app_l2cat.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CAT_MBA/allocation_app_l2cat.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CAT_MBA/allocation_app_l3cat.c intel-cmt-cat-4.0/examples/c/CAT_MBA/allocation_app_l3cat.c --- intel-cmt-cat-3.2/examples/c/CAT_MBA/allocation_app_l3cat.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CAT_MBA/allocation_app_l3cat.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CAT_MBA/allocation_app_mba.c intel-cmt-cat-4.0/examples/c/CAT_MBA/allocation_app_mba.c --- intel-cmt-cat-3.2/examples/c/CAT_MBA/allocation_app_mba.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CAT_MBA/allocation_app_mba.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CAT_MBA/association_app.c intel-cmt-cat-4.0/examples/c/CAT_MBA/association_app.c --- intel-cmt-cat-3.2/examples/c/CAT_MBA/association_app.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CAT_MBA/association_app.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CAT_MBA/Makefile intel-cmt-cat-4.0/examples/c/CAT_MBA/Makefile --- intel-cmt-cat-3.2/examples/c/CAT_MBA/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CAT_MBA/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2018-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2018-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CAT_MBA/reset_app.c intel-cmt-cat-4.0/examples/c/CAT_MBA/reset_app.c --- intel-cmt-cat-3.2/examples/c/CAT_MBA/reset_app.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CAT_MBA/reset_app.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CMT_MBM/Makefile intel-cmt-cat-4.0/examples/c/CMT_MBM/Makefile --- intel-cmt-cat-3.2/examples/c/CMT_MBM/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CMT_MBM/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/CMT_MBM/monitor_app.c intel-cmt-cat-4.0/examples/c/CMT_MBM/monitor_app.c --- intel-cmt-cat-3.2/examples/c/CMT_MBM/monitor_app.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/CMT_MBM/monitor_app.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -335,8 +335,7 @@ return; } if (!process_mode()) { - printf(" CORE RMID LLC[KB]" - " MBL[MB] MBR[MB]\n"); + printf(" CORE LLC[KB] MBL[MB] MBR[MB]\n"); for (i = 0; i < sel_monitor_num; i++) { const struct pqos_event_values *pv = &m_mon_grps[i]->values; @@ -344,16 +343,10 @@ double mbr = bytes_to_mb(pv->mbm_remote_delta); double mbl = bytes_to_mb(pv->mbm_local_delta); - if (interface == PQOS_INTER_OS) - printf("%8u %s %10.1f %10.1f %10.1f\n", - m_mon_grps[i]->cores[0], - " N/A", llc, mbl, mbr); - else - printf("%8u %8u %10.1f %10.1f %10.1f\n", - m_mon_grps[i]->cores[0], - m_mon_grps[i]->poll_ctx[0].rmid, - llc, mbl, mbr); + printf("%8u %10.1f %10.1f %10.1f\n", + m_mon_grps[i]->cores[0], llc, mbl, mbr); } + } else { printf("PID LLC[KB]\n"); for (i = 0; i < sel_process_num; i++) { diff -Nru intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/dlock.c intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/dlock.c --- intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/dlock.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/dlock.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ #include "dlock.h" #define MAX_L3CAT_NUM 16 -#define DIM(x) (sizeof(x)/sizeof(x[0])) +#define DIM(x) (sizeof(x) / sizeof(x[0])) static int m_is_chunk_allocated = 0; static char *m_chunk_start = NULL; diff -Nru intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/dlock.h intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/dlock.h --- intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/dlock.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/dlock.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/Makefile intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/Makefile --- intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/pseudo_lock.c intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/pseudo_lock.c --- intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/pseudo_lock.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/pseudo_lock.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/tsc.c intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/tsc.c --- intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/tsc.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/tsc.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/tsc.h intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/tsc.h --- intel-cmt-cat-3.2/examples/c/PSEUDO_LOCK/tsc.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/c/PSEUDO_LOCK/tsc.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/perl/hello_world.pl intel-cmt-cat-4.0/examples/perl/hello_world.pl --- intel-cmt-cat-3.2/examples/perl/hello_world.pl 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/perl/hello_world.pl 2020-06-19 10:42:55.000000000 +0000 @@ -3,7 +3,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/perl/Makefile intel-cmt-cat-4.0/examples/perl/Makefile --- intel-cmt-cat-3.2/examples/perl/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/perl/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/association.py intel-cmt-cat-4.0/examples/python/association.py --- intel-cmt-cat-3.2/examples/python/association.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/association.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/l2ca.py intel-cmt-cat-4.0/examples/python/l2ca.py --- intel-cmt-cat-3.2/examples/python/l2ca.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/l2ca.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/l3ca.py intel-cmt-cat-4.0/examples/python/l3ca.py --- intel-cmt-cat-3.2/examples/python/l3ca.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/l3ca.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/Makefile intel-cmt-cat-4.0/examples/python/Makefile --- intel-cmt-cat-3.2/examples/python/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/mba.py intel-cmt-cat-4.0/examples/python/mba.py --- intel-cmt-cat-3.2/examples/python/mba.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/mba.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/monitoring.py intel-cmt-cat-4.0/examples/python/monitoring.py --- intel-cmt-cat-3.2/examples/python/monitoring.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/monitoring.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/examples/python/reset_allocation.py intel-cmt-cat-4.0/examples/python/reset_allocation.py --- intel-cmt-cat-3.2/examples/python/reset_allocation.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/examples/python/reset_allocation.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/.github/PULL_REQUEST_TEMPLATE.md intel-cmt-cat-4.0/.github/PULL_REQUEST_TEMPLATE.md --- intel-cmt-cat-3.2/.github/PULL_REQUEST_TEMPLATE.md 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/.github/PULL_REQUEST_TEMPLATE.md 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,34 @@ + + +## Description + + +## Affected parts + + +- [ ] library +- [ ] pqos utility +- [ ] rdtset utility +- [ ] other: (please specify) + +## Motivation and Context + + + +## How Has This Been Tested? + + + + +## Types of changes + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) + +## Checklist: + + +- [ ] My code follows the code style of this project. +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. diff -Nru intel-cmt-cat-3.2/.gitignore intel-cmt-cat-4.0/.gitignore --- intel-cmt-cat-3.2/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/.gitignore 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,29 @@ +*.o +*.so +*.so.* +*.a +*.xml +*.log +*.d +*.pyc +pqos/pqos +rdtset/rdtset + +examples/c/CAT_MBA/allocation_app_l2cat +examples/c/CAT_MBA/allocation_app_l3cat +examples/c/CAT_MBA/allocation_app_mba +examples/c/CAT_MBA/association_app +examples/c/CAT_MBA/reset_app +examples/c/CMT_MBM/monitor_app +examples/c/PSEUDO_LOCK/pseudo_lock + +tools/membw/membw + +appqos/appqos.crt +appqos/appqos.key +appqos/env_* + +lib/python/.coverage +lib/python/test_env + +bat/test_env diff -Nru intel-cmt-cat-3.2/lib/allocation.c intel-cmt-cat-4.0/lib/allocation.c --- intel-cmt-cat-3.2/lib/allocation.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/allocation.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,7 @@ #include "types.h" #include "log.h" #include "cpu_registers.h" +#include "cpuinfo.h" /** * --------------------------------------- @@ -60,7 +61,6 @@ * --------------------------------------- */ - /** * --------------------------------------- * Local data types @@ -87,70 +87,6 @@ */ /** - * @brief Gets highest COS id which could be used to configure set technologies - * - * @param [in] technology technologies bitmask to get highest common COS id for - * @param [out] hi_class_id highest common COS id - * - * @return Operation status - */ -static int -get_hi_cos_id(const unsigned technology, - unsigned *hi_class_id) -{ - const int l2_req = ((technology & (1 << PQOS_CAP_TYPE_L2CA)) != 0); - const int l3_req = ((technology & (1 << PQOS_CAP_TYPE_L3CA)) != 0); - const int mba_req = ((technology & (1 << PQOS_CAP_TYPE_MBA)) != 0); - unsigned num_l2_cos = 0, num_l3_cos = 0, num_mba_cos = 0, num_cos = 0; - int ret; - const struct pqos_cap *cap; - - ASSERT(l2_req || l3_req || mba_req); - if (hi_class_id == NULL) - return PQOS_RETVAL_PARAM; - - _pqos_cap_get(&cap, NULL); - - if (l3_req) { - ret = pqos_l3ca_get_cos_num(cap, &num_l3_cos); - if (ret != PQOS_RETVAL_OK && ret != PQOS_RETVAL_RESOURCE) - return ret; - - if (num_l3_cos == 0) - return PQOS_RETVAL_ERROR; - - num_cos = num_l3_cos; - } - - if (l2_req) { - ret = pqos_l2ca_get_cos_num(cap, &num_l2_cos); - if (ret != PQOS_RETVAL_OK && ret != PQOS_RETVAL_RESOURCE) - return ret; - if (num_l2_cos == 0) - return PQOS_RETVAL_ERROR; - - if (num_cos == 0 || num_l2_cos < num_cos) - num_cos = num_l2_cos; - } - - if (mba_req) { - ret = pqos_mba_get_cos_num(cap, &num_mba_cos); - if (ret != PQOS_RETVAL_OK && ret != PQOS_RETVAL_RESOURCE) - return ret; - - if (num_mba_cos == 0) - return PQOS_RETVAL_ERROR; - - if (num_cos == 0 || num_mba_cos < num_cos) - num_cos = num_mba_cos; - } - - *hi_class_id = num_cos - 1; - - return PQOS_RETVAL_OK; -} - -/** * @brief Gets COS associated to \a lcore * * @param [in] lcore lcore to read COS association from @@ -171,7 +107,7 @@ return PQOS_RETVAL_ERROR; val >>= PQOS_MSR_ASSOC_QECOS_SHIFT; - *class_id = (unsigned) val; + *class_id = (unsigned)val; return PQOS_RETVAL_OK; } @@ -181,8 +117,10 @@ * * The lowest acceptable COS is 1, as 0 is a default one * - * @param [in] id socket or L2 cache ID to search for unused COS on * @param [in] technology selection of allocation technologies + * @param [in] l3cat_id L3 CAT resource id + * @param [in] l2cat_id L2 CAT resource id + * @param [in] mba_id MBA resource id * @param [out] class_id unused COS * * NOTE: It is our assumption that mba id and cat ids are same for @@ -192,48 +130,96 @@ * @return Operation status */ static int -get_unused_cos(const unsigned id, - const unsigned technology, +get_unused_cos(const unsigned technology, + unsigned l3cat_id, + unsigned l2cat_id, + unsigned mba_id, unsigned *class_id) { - const int l2_req = ((technology & (1 << PQOS_CAP_TYPE_L2CA)) != 0); - const int mba_req = ((technology & (1 << PQOS_CAP_TYPE_MBA)) != 0); - unsigned used_classes[PQOS_MAX_L3CA_COS]; + unsigned num_l2_cos = 0, num_l3_cos = 0, num_mba_cos = 0; + unsigned num_cos = 0; unsigned i, cos; - unsigned hi_class_id; int ret; + const int l2_req = ((technology & (1 << PQOS_CAP_TYPE_L2CA)) != 0); + const int l3_req = ((technology & (1 << PQOS_CAP_TYPE_L3CA)) != 0); + const int mba_req = ((technology & (1 << PQOS_CAP_TYPE_MBA)) != 0); + int l2cat_id_set = l2_req; + int l3cat_id_set = l3_req; + int mba_id_set = mba_req; + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + unsigned used_classes[PQOS_MAX_COS]; if (class_id == NULL) return PQOS_RETVAL_PARAM; - /* obtain highest class id for all requested technologies */ - ret = get_hi_cos_id(technology, &hi_class_id); - if (ret != PQOS_RETVAL_OK) - return ret; + _pqos_cap_get(&cap, &cpu); memset(used_classes, 0, sizeof(used_classes)); - /* Create a list of COS used on socket/L2 cluster */ - for (i = 0; i < m_cpu->num_cores; i++) { - if (l2_req) { - /* L2 requested so looking in L2 cluster scope */ - if (m_cpu->cores[i].l2_id != id) - continue; - } else if (mba_req) { - /* mba requested so looking in mba_id scope */ - if (m_cpu->cores[i].mba_id != id) - continue; - } else { - /* looking at l3cat_id scope */ - if (m_cpu->cores[i].l3cat_id != id) - continue; - } + ret = pqos_l3ca_get_cos_num(cap, &num_l3_cos); + if (ret != PQOS_RETVAL_OK && ret != PQOS_RETVAL_RESOURCE) + return ret; + + ret = pqos_l2ca_get_cos_num(cap, &num_l2_cos); + if (ret != PQOS_RETVAL_OK && ret != PQOS_RETVAL_RESOURCE) + return ret; + + ret = pqos_mba_get_cos_num(cap, &num_mba_cos); + if (ret != PQOS_RETVAL_OK && ret != PQOS_RETVAL_RESOURCE) + return ret; + + /* Obtain highest COS number for requested technologies */ + { + if (l3_req) + num_cos = num_l3_cos; + + if (l2_req && (num_cos == 0 || num_cos > num_l2_cos)) + num_cos = num_l2_cos; + + if (mba_req && (num_cos == 0 || num_cos > num_mba_cos)) + num_cos = num_mba_cos; + + if (num_cos == 0) + return PQOS_RETVAL_ERROR; + } + + /* Obtain L3 and MBA ids for L2 cluster*/ + if (l2_req && !l3cat_id_set && !mba_id_set) { + for (i = 0; i < cpu->num_cores; i++) + if (cpu->cores[i].l2_id == l2cat_id) { + + if (num_l3_cos > 0 && !l3cat_id_set) { + l3cat_id = cpu->cores[i].l3cat_id; + l3cat_id_set = 1; + break; + } + if (num_mba_cos > 0 && !mba_id_set) { + mba_id = cpu->cores[i].mba_id; + mba_id_set = 1; + break; + } + } + } - ret = cos_assoc_get(m_cpu->cores[i].lcore, &cos); + /* Create a list of used COS */ + for (i = 0; i < cpu->num_cores; i++) { + if (l3cat_id_set && cpu->cores[i].l3cat_id != l3cat_id) + continue; + if (mba_id_set && cpu->cores[i].mba_id != mba_id) + continue; + + ret = cos_assoc_get(cpu->cores[i].lcore, &cos); if (ret != PQOS_RETVAL_OK) return ret; - if (cos > hi_class_id) + if (cos >= num_cos) + continue; + + /* COS does not support L3CAT and MBA need to check + L2 cluster only */ + if (cos >= num_l3_cos && cos >= num_mba_cos && l2cat_id_set && + cpu->cores[i].l2_id != l2cat_id) continue; /* Mark as used */ @@ -241,7 +227,7 @@ } /* Find unused COS */ - for (cos = hi_class_id; cos != 0; cos--) { + for (cos = num_cos - 1; cos != 0; cos--) { if (used_classes[cos] == 0) { *class_id = cos; return PQOS_RETVAL_OK; @@ -323,7 +309,7 @@ ret = pqos_l3ca_get_cos_num(cap, &count); if (ret != PQOS_RETVAL_OK) - return ret; /**< perhaps no L3CA capability */ + return ret; /**< perhaps no L3CA capability */ if (num_ca > count) return PQOS_RETVAL_ERROR; @@ -340,7 +326,7 @@ if (cdp_enabled) { for (i = 0; i < num_ca; i++) { uint32_t reg = - (ca[i].class_id*2) + PQOS_MSR_L3CA_MASK_START; + (ca[i].class_id * 2) + PQOS_MSR_L3CA_MASK_START; int retval = MACHINE_RETVAL_OK; uint64_t cmask = 0, dmask = 0; @@ -356,14 +342,14 @@ if (retval != MACHINE_RETVAL_OK) return PQOS_RETVAL_ERROR; - retval = msr_write(core, reg+1, cmask); + retval = msr_write(core, reg + 1, cmask); if (retval != MACHINE_RETVAL_OK) return PQOS_RETVAL_ERROR; } } else { for (i = 0; i < num_ca; i++) { uint32_t reg = - ca[i].class_id + PQOS_MSR_L3CA_MASK_START; + ca[i].class_id + PQOS_MSR_L3CA_MASK_START; uint64_t val = ca[i].u.ways_mask; int retval = MACHINE_RETVAL_OK; @@ -403,7 +389,7 @@ ret = pqos_l3ca_get_cos_num(cap, &count); if (ret != PQOS_RETVAL_OK) - return ret; /**< perhaps no L3CA capability */ + return ret; /**< perhaps no L3CA capability */ ret = pqos_l3ca_cdp_enabled(cap, NULL, &cdp_enabled); if (ret != PQOS_RETVAL_OK) @@ -418,8 +404,8 @@ return ret; if (cdp_enabled) { - for (i = 0, reg = PQOS_MSR_L3CA_MASK_START; - i < count; i++, reg += 2) { + for (i = 0, reg = PQOS_MSR_L3CA_MASK_START; i < count; + i++, reg += 2) { ca[i].cdp = 1; ca[i].class_id = i; @@ -436,8 +422,8 @@ ca[i].u.s.code_mask = val; } } else { - for (i = 0, reg = PQOS_MSR_L3CA_MASK_START; - i < count; i++, reg++) { + for (i = 0, reg = PQOS_MSR_L3CA_MASK_START; i < count; + i++, reg++) { retval = msr_read(core, reg, &val); if (retval != MACHINE_RETVAL_OK) return PQOS_RETVAL_ERROR; @@ -485,7 +471,7 @@ * Find free COS */ for (l3cat_id = 0; l3cat_id < l3cat_id_num; l3cat_id++) { - ret = get_unused_cos(l3cat_id, technology, &class_id); + ret = get_unused_cos(technology, l3cat_id, 0, 0, &class_id); if (ret == PQOS_RETVAL_OK) break; @@ -528,8 +514,8 @@ /** * Validate if mask was correctly set */ - ret = hw_l3ca_get(l3cat_id, PQOS_MAX_L3CA_COS, &num_ca, - l3ca_tab); + ret = + hw_l3ca_get(l3cat_id, PQOS_MAX_L3CA_COS, &num_ca, l3ca_tab); if (ret != PQOS_RETVAL_OK) goto pqos_l3ca_get_min_cbm_bits_restore; @@ -539,9 +525,8 @@ if (l3ca->class_id != class_id) continue; - if ((l3ca->cdp && - l3ca->u.s.data_mask == mask && - l3ca->u.s.code_mask == mask) || + if ((l3ca->cdp && l3ca->u.s.data_mask == mask && + l3ca->u.s.code_mask == mask) || (!l3ca->cdp && l3ca->u.ways_mask == mask)) { *min_cbm_bits = ways; ret = PQOS_RETVAL_OK; @@ -553,7 +538,7 @@ /** * Restore old settings */ - pqos_l3ca_get_min_cbm_bits_restore: +pqos_l3ca_get_min_cbm_bits_restore: for (i = 0; i < l3ca_num; i++) { int ret_val; @@ -569,7 +554,7 @@ } } - pqos_l3ca_get_min_cbm_bits_exit: +pqos_l3ca_get_min_cbm_bits_exit: if (l3cat_ids != NULL) free(l3cat_ids); @@ -625,7 +610,7 @@ for (i = 0; i < num_ca; i++) { if (cdp_enabled) { uint32_t reg = - (ca[i].class_id * 2) + PQOS_MSR_L2CA_MASK_START; + (ca[i].class_id * 2) + PQOS_MSR_L2CA_MASK_START; int retval = MACHINE_RETVAL_OK; uint64_t cmask = 0, dmask = 0; @@ -646,7 +631,7 @@ return PQOS_RETVAL_ERROR; } else { uint32_t reg = - ca[i].class_id + PQOS_MSR_L2CA_MASK_START; + ca[i].class_id + PQOS_MSR_L2CA_MASK_START; uint64_t val = ca[i].u.ways_mask; int retval; @@ -758,8 +743,8 @@ return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ /** - * Get number & list of L2ids in the system - */ + * Get number & list of L2ids in the system + */ l2ids = pqos_cpu_get_l2ids(m_cpu, &l2id_num); if (l2ids == NULL || l2id_num == 0) { ret = PQOS_RETVAL_ERROR; @@ -770,7 +755,7 @@ * Find free COS */ for (l2id = 0; l2id < l2id_num; l2id++) { - ret = get_unused_cos(l2id, technology, &class_id); + ret = get_unused_cos(technology, 0, l2id, 0, &class_id); if (ret == PQOS_RETVAL_OK) break; if (ret != PQOS_RETVAL_RESOURCE) @@ -822,9 +807,8 @@ if (l2ca->class_id != class_id) continue; - if ((l2ca->cdp && - l2ca->u.s.data_mask == mask && - l2ca->u.s.code_mask == mask) || + if ((l2ca->cdp && l2ca->u.s.data_mask == mask && + l2ca->u.s.code_mask == mask) || (!l2ca->cdp && l2ca->u.ways_mask == mask)) { *min_cbm_bits = ways; ret = PQOS_RETVAL_OK; @@ -836,7 +820,7 @@ /** * Restore old settings */ - hw_l2ca_get_min_cbm_bits_restore: +hw_l2ca_get_min_cbm_bits_restore: for (i = 0; i < l2ca_num; i++) { int ret_val; @@ -852,7 +836,7 @@ } } - hw_l2ca_get_min_cbm_bits_exit: +hw_l2ca_get_min_cbm_bits_exit: if (l2ids != NULL) free(l2ids); @@ -913,9 +897,10 @@ for (i = 0; i < num_cos; i++) { const uint32_t reg = - requested[i].class_id + PQOS_MSR_MBA_MASK_START; - uint64_t val = PQOS_MBA_LINEAR_MAX - - (((requested[i].mb_max + (step/2)) / step) * step); + requested[i].class_id + PQOS_MSR_MBA_MASK_START; + uint64_t val = + PQOS_MBA_LINEAR_MAX - + (((requested[i].mb_max + (step / 2)) / step) * step); int retval = MACHINE_RETVAL_OK; if (val > mba_cap->u.mba->throttle_max) @@ -944,6 +929,78 @@ } int +hw_mba_set_amd(const unsigned mba_id, + const unsigned num_cos, + const struct pqos_mba *requested, + struct pqos_mba *actual) +{ + int ret = PQOS_RETVAL_OK; + unsigned i = 0, count = 0, core = 0; + const struct pqos_capability *mba_cap = NULL; + + ASSERT(requested != NULL); + ASSERT(num_cos != 0); + + /** + * Check if MBA is supported + */ + ret = _pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &mba_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* MBA not supported */ + + count = mba_cap->u.mba->num_classes; + + /** + * Check if class id's are within allowed range + * and if a controller is not requested. + */ + for (i = 0; i < num_cos; i++) { + if (requested[i].class_id >= count) { + LOG_ERROR("MBA COS%u is out of range (COS%u is max)!\n", + requested[i].class_id, count - 1); + return PQOS_RETVAL_PARAM; + } + + if (requested[i].ctrl != 0) { + LOG_ERROR("MBA controller not supported!\n"); + return PQOS_RETVAL_PARAM; + } + } + + ASSERT(m_cpu != NULL); + ret = pqos_cpu_get_one_by_mba_id(m_cpu, mba_id, &core); + if (ret != PQOS_RETVAL_OK) + return ret; + + for (i = 0; i < num_cos; i++) { + const uint32_t reg = + requested[i].class_id + PQOS_MSR_MBA_MASK_START_AMD; + uint64_t val = requested[i].mb_max; + int retval = MACHINE_RETVAL_OK; + + retval = msr_write(core, reg, val); + if (retval != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + /** + * If table to store actual values set is passed, + * read MSR values and store in table + */ + if (actual == NULL) + continue; + + retval = msr_read(core, reg, &val); + if (retval != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + actual[i] = requested[i]; + actual[i].mb_max = val; + } + + return ret; +} + +int hw_mba_get(const unsigned mba_id, const unsigned max_num_cos, unsigned *num_cos, @@ -961,7 +1018,7 @@ ret = pqos_mba_get_cos_num(cap, &count); if (ret != PQOS_RETVAL_OK) - return ret; /**< no MBA capability */ + return ret; /**< no MBA capability */ if (count > max_num_cos) return PQOS_RETVAL_ERROR; @@ -981,13 +1038,57 @@ mba_tab[i].ctrl = 0; mba_tab[i].class_id = i; - mba_tab[i].mb_max = (unsigned) PQOS_MBA_LINEAR_MAX - val; + mba_tab[i].mb_max = (unsigned)PQOS_MBA_LINEAR_MAX - val; } *num_cos = count; return ret; } +int +hw_mba_get_amd(const unsigned mba_id, + const unsigned max_num_cos, + unsigned *num_cos, + struct pqos_mba *mba_tab) +{ + int ret = PQOS_RETVAL_OK; + unsigned i = 0, count = 0, core = 0; + const struct pqos_cap *cap; + + ASSERT(num_cos != NULL); + ASSERT(mba_tab != NULL); + ASSERT(max_num_cos != 0); + + _pqos_cap_get(&cap, NULL); + + ret = pqos_mba_get_cos_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return ret; /**< no MBA capability */ + + if (count > max_num_cos) + return PQOS_RETVAL_ERROR; + + ASSERT(m_cpu != NULL); + ret = pqos_cpu_get_one_by_mba_id(m_cpu, mba_id, &core); + if (ret != PQOS_RETVAL_OK) + return ret; + + for (i = 0; i < count; i++) { + const uint32_t reg = PQOS_MSR_MBA_MASK_START_AMD + i; + uint64_t val = 0; + int retval = msr_read(core, reg, &val); + + if (retval != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + mba_tab[i].ctrl = 0; + mba_tab[i].class_id = i; + mba_tab[i].mb_max = val; + } + *num_cos = count; + + return ret; +} /** * @brief Sets COS associated to \a lcore * @@ -1008,7 +1109,7 @@ return PQOS_RETVAL_ERROR; val &= (~PQOS_MSR_ASSOC_QECOS_MASK); - val |= (((uint64_t) class_id) << PQOS_MSR_ASSOC_QECOS_SHIFT); + val |= (((uint64_t)class_id) << PQOS_MSR_ASSOC_QECOS_SHIFT); ret = msr_write(lcore, reg, val); if (ret != MACHINE_RETVAL_OK) @@ -1018,8 +1119,7 @@ } int -hw_alloc_assoc_set(const unsigned lcore, - const unsigned class_id) +hw_alloc_assoc_set(const unsigned lcore, const unsigned class_id) { int ret = PQOS_RETVAL_OK; unsigned num_l2_cos = 0, num_l3_cos = 0; @@ -1050,8 +1150,7 @@ } int -hw_alloc_assoc_get(const unsigned lcore, - unsigned *class_id) +hw_alloc_assoc_get(const unsigned lcore, unsigned *class_id) { const struct pqos_capability *l3_cap = NULL; const struct pqos_capability *l2_cap = NULL; @@ -1085,16 +1184,16 @@ return ret; } - int hw_alloc_assign(const unsigned technology, const unsigned *core_array, const unsigned core_num, unsigned *class_id) { + const int l3_req = ((technology & (1 << PQOS_CAP_TYPE_L3CA)) != 0); const int l2_req = ((technology & (1 << PQOS_CAP_TYPE_L2CA)) != 0); - const int mba_req = ((technology & (1 << PQOS_CAP_TYPE_MBA)) != 0); - unsigned resource_id = 0; + const int mba_req = ((technology & (1 << PQOS_CAP_TYPE_MBA)) != 0); + unsigned l3cat_id = 0, l2cat_id = 0, mba_id = 0; unsigned i; int ret; @@ -1113,33 +1212,34 @@ goto pqos_alloc_assign_exit; } - if (l2_req) { - /* L2 is requested - * The smallest manageable entity is L2 cluster - */ - if (i != 0 && resource_id != pi->l2_id) { + if (l3_req) { + if (i != 0 && l3cat_id != pi->l3cat_id) { + ret = PQOS_RETVAL_PARAM; + goto pqos_alloc_assign_exit; + } + l3cat_id = pi->l3cat_id; + } + if (mba_req) { + if (i != 0 && mba_id != pi->mba_id) { ret = PQOS_RETVAL_PARAM; goto pqos_alloc_assign_exit; } - resource_id = pi->l2_id; - } else if (mba_req) { - if (i != 0 && resource_id != pi->mba_id) { - ret = PQOS_RETVAL_PARAM; - goto pqos_alloc_assign_exit; - } - resource_id = pi->mba_id; - } else { - if (i != 0 && resource_id != pi->l3cat_id) { + mba_id = pi->mba_id; + } + if (l2_req && !l3_req && !mba_req) { + /* only L2 is requested + * The smallest manageable entity is L2 cluster + */ + if (i != 0 && l2cat_id != pi->l2_id) { ret = PQOS_RETVAL_PARAM; goto pqos_alloc_assign_exit; } - resource_id = pi->l3cat_id; + l2cat_id = pi->l2_id; } } /* find an unused class from highest down */ - ret = get_unused_cos(resource_id, technology, class_id); - + ret = get_unused_cos(technology, l3cat_id, l2cat_id, mba_id, class_id); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_assign_exit; @@ -1150,13 +1250,12 @@ goto pqos_alloc_assign_exit; } - pqos_alloc_assign_exit: +pqos_alloc_assign_exit: return ret; } int -hw_alloc_release(const unsigned *core_array, - const unsigned core_num) +hw_alloc_release(const unsigned *core_array, const unsigned core_num) { unsigned i; int ret = PQOS_RETVAL_OK; @@ -1231,9 +1330,7 @@ * @retval PQOS_RETVAL_ERROR on failure, MSR read/write error */ static int -l2cdp_enable(const unsigned l2id_num, - const unsigned *l2ids, - const int enable) +l2cdp_enable(const unsigned l2id_num, const unsigned *l2ids, const int enable) { unsigned i = 0; int ret; @@ -1339,6 +1436,7 @@ const struct pqos_cap_l3ca *l3_cap = NULL; const struct pqos_cap_l2ca *l2_cap = NULL; const struct pqos_cap_mba *mba_cap = NULL; + const struct cpuinfo_config *vconfig; int ret = PQOS_RETVAL_OK; unsigned max_l3_cos = 0; unsigned max_l2_cos = 0; @@ -1353,26 +1451,26 @@ l2_cdp_cfg == PQOS_REQUIRE_CDP_OFF || l2_cdp_cfg == PQOS_REQUIRE_CDP_ANY); - ASSERT(mba_cfg == PQOS_MBA_DEFAULT || - mba_cfg == PQOS_MBA_CTRL || + ASSERT(mba_cfg == PQOS_MBA_DEFAULT || mba_cfg == PQOS_MBA_CTRL || mba_cfg == PQOS_MBA_ANY); _pqos_cap_get(&cap, NULL); + cpuinfo_get_config(&vconfig); /* Get L3 CAT capabilities */ - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &alloc_cap); if (alloc_cap != NULL) l3_cap = alloc_cap->u.l3ca; /* Get L2 CAT capabilities */ alloc_cap = NULL; - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &alloc_cap); if (alloc_cap != NULL) l2_cap = alloc_cap->u.l2ca; /* Get MBA capabilities */ alloc_cap = NULL; - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &alloc_cap); if (alloc_cap != NULL) mba_cap = alloc_cap->u.mba; @@ -1458,14 +1556,13 @@ for (j = 0; j < l3cat_id_num; j++) { unsigned core = 0; - ret = pqos_cpu_get_one_by_l3cat_id(m_cpu, - l3cat_ids[j], + ret = pqos_cpu_get_one_by_l3cat_id(m_cpu, l3cat_ids[j], &core); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; const uint64_t ways_mask = - (1ULL << l3_cap->num_ways) - 1ULL; + (1ULL << l3_cap->num_ways) - 1ULL; ret = alloc_cos_reset(PQOS_MSR_L3CA_MASK_START, max_l3_cos, core, ways_mask); @@ -1485,7 +1582,7 @@ for (j = 0; j < l2id_num; j++) { const uint64_t ways_mask = - (1ULL << l2_cap->num_ways) - 1ULL; + (1ULL << l2_cap->num_ways) - 1ULL; unsigned core = 0; ret = pqos_cpu_get_one_by_l2id(m_cpu, l2ids[j], &core); @@ -1519,8 +1616,9 @@ if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; - ret = alloc_cos_reset(PQOS_MSR_MBA_MASK_START, - mba_cap->num_classes, core, 0); + ret = alloc_cos_reset(vconfig->mba_msr_reg, + mba_cap->num_classes, core, + vconfig->mba_default_val); if (ret != PQOS_RETVAL_OK) goto pqos_alloc_reset_exit; } @@ -1593,7 +1691,7 @@ _pqos_cap_l2cdp_change(l2_cdp_cfg); } - pqos_alloc_reset_exit: +pqos_alloc_reset_exit: if (l3cat_ids != NULL) free(l3cat_ids); if (mba_ids != NULL) diff -Nru intel-cmt-cat-3.2/lib/allocation.h intel-cmt-cat-4.0/lib/allocation.h --- intel-cmt-cat-3.2/lib/allocation.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/allocation.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -74,8 +74,7 @@ * * @return Operations status */ -int hw_alloc_assoc_set(const unsigned lcore, - const unsigned class_id); +int hw_alloc_assoc_set(const unsigned lcore, const unsigned class_id); /** * @brief Hardware interface to read association @@ -87,8 +86,7 @@ * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int hw_alloc_assoc_get(const unsigned lcore, - unsigned *class_id); +int hw_alloc_assoc_get(const unsigned lcore, unsigned *class_id); /** * @brief Hardware interface to assign first available @@ -124,8 +122,7 @@ * * @return Operations status */ -int hw_alloc_release(const unsigned *core_array, - const unsigned core_num); +int hw_alloc_release(const unsigned *core_array, const unsigned core_num); /** * @brief Hardware interface to reset configuration @@ -259,6 +256,24 @@ struct pqos_mba *actual); /** + * @brief Hardware interface to set classes of service + * defined by \a requested on \a mba_id + * @NOTE: This function is specific to AMD + * + * @param [in] mba_id + * @param [in] num_cos number of classes of service at \a ca + * @param [in] requested table with class of service definitions + * @param [out] actual table with class of service definitions + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int hw_mba_set_amd(const unsigned mba_id, + const unsigned num_cos, + const struct pqos_mba *requested, + struct pqos_mba *actual); + +/** * @brief Hardware interface to read MBA from \a mba_id * * @param [in] mba_id MBA resource id @@ -275,6 +290,24 @@ unsigned *num_cos, struct pqos_mba *mba_tab); +/** + * @brief Hardware interface to read MBA from \a mba_id + * @NOTE: This function is specific to AMD + * + * @param [in] mba_id MBA resource id + * @param [in] max_num_cos maximum number of classes of service + * that can be accommodated at \a mba_tab + * @param [out] num_cos number of classes of service read into \a mba_tab + * @param [out] mba_tab table with read classes of service + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int hw_mba_get_amd(const unsigned mba_id, + const unsigned max_num_cos, + unsigned *num_cos, + struct pqos_mba *mba_tab); + #ifdef __cplusplus } #endif diff -Nru intel-cmt-cat-3.2/lib/api.c intel-cmt-cat-4.0/lib/api.c --- intel-cmt-cat-3.2/lib/api.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/api.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ */ #include +#include #include "pqos.h" #include "api.h" @@ -41,10 +42,11 @@ #include "os_monitoring.h" #include "monitoring.h" #include "os_monitoring.h" +#include "hw_monitoring.h" #include "cap.h" #include "log.h" #include "types.h" -#include "cpu_registers.h" +#include "cpuinfo.h" /** * Value marking monitoring group structure as "valid". @@ -60,20 +62,87 @@ */ static int m_interface = PQOS_INTER_MSR; +/** + * PQoS API functions + */ +static struct pqos_api { + /** Starts resource monitoring on selected group of cores */ + int (*mon_start)(const unsigned num_cores, + const unsigned *cores, + const enum pqos_mon_event event, + void *context, + struct pqos_mon_data *group); + /** Starts resource monitoring of selected pids */ + int (*mon_start_pids)(const unsigned num_pids, + const pid_t *pids, + const enum pqos_mon_event event, + void *context, + struct pqos_mon_data *group); + /*Stops resource monitoring data for selected monitoring group */ + int (*mon_stop)(struct pqos_mon_data *group); + + /** Set MBA */ + int (*mba_get)(const unsigned mba_id, + const unsigned max_num_cos, + unsigned *num_cos, + struct pqos_mba *mba_tab); + /** Get MBA mask */ + int (*mba_set)(const unsigned mba_id, + const unsigned num_cos, + const struct pqos_mba *requested, + struct pqos_mba *actual); + /** Assign first available COS */ + int (*alloc_assign)(const unsigned technology, + const unsigned *core_array, + const unsigned core_num, + unsigned *class_id); +} api; + /* * ======================================= * Init module * ======================================= */ int -api_init(int interface) +api_init(int interface, enum pqos_vendor vendor) { if (interface != PQOS_INTER_MSR && interface != PQOS_INTER_OS && - interface != PQOS_INTER_OS_RESCTRL_MON) + interface != PQOS_INTER_OS_RESCTRL_MON) return PQOS_RETVAL_PARAM; m_interface = interface; + memset(&api, 0, sizeof(api)); + + if (interface == PQOS_INTER_MSR) { + api.mon_start = hw_mon_start; + api.mon_stop = hw_mon_stop; + if (vendor == PQOS_VENDOR_AMD) { + api.mba_get = hw_mba_get_amd; + api.mba_set = hw_mba_set_amd; + } else { + api.mba_get = hw_mba_get; + api.mba_set = hw_mba_set; + } + api.alloc_assign = hw_alloc_assign; + +#ifdef __linux__ + } else if (interface == PQOS_INTER_OS || + interface == PQOS_INTER_OS_RESCTRL_MON) { + api.mon_start = os_mon_start; + api.mon_start_pids = os_mon_start_pids; + api.mon_stop = os_mon_stop; + if (vendor == PQOS_VENDOR_AMD) { + api.mba_get = os_mba_get_amd; + api.mba_set = os_mba_set_amd; + } else { + api.mba_get = os_mba_get; + api.mba_set = os_mba_set; + } + api.alloc_assign = os_alloc_assign; +#endif + } + return PQOS_RETVAL_OK; } @@ -83,8 +152,7 @@ * ======================================= */ int -pqos_alloc_assoc_set(const unsigned lcore, - const unsigned class_id) +pqos_alloc_assoc_set(const unsigned lcore, const unsigned class_id) { int ret; @@ -112,8 +180,7 @@ } int -pqos_alloc_assoc_get(const unsigned lcore, - unsigned *class_id) +pqos_alloc_assoc_get(const unsigned lcore, unsigned *class_id) { int ret; @@ -144,8 +211,7 @@ } int -pqos_alloc_assoc_set_pid(const pid_t task, - const unsigned class_id) +pqos_alloc_assoc_set_pid(const pid_t task, const unsigned class_id) { int ret; @@ -158,7 +224,7 @@ } if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task association!\n"); _pqos_api_unlock(); @@ -176,12 +242,10 @@ _pqos_api_unlock(); return ret; - } int -pqos_alloc_assoc_get_pid(const pid_t task, - unsigned *class_id) +pqos_alloc_assoc_get_pid(const pid_t task, unsigned *class_id) { int ret; @@ -197,7 +261,7 @@ } if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task association!\n"); _pqos_api_unlock(); @@ -239,17 +303,13 @@ _pqos_api_unlock(); return ret; } - if (m_interface == PQOS_INTER_MSR) - ret = hw_alloc_assign(technology, core_array, - core_num, class_id); + + if (api.alloc_assign != NULL) + ret = api.alloc_assign(technology, core_array, core_num, + class_id); else { -#ifdef __linux__ - ret = os_alloc_assign(technology, core_array, core_num, - class_id); -#else - LOG_INFO("OS interface not supported!\n"); + LOG_INFO("Interface not supported!\n"); ret = PQOS_RETVAL_RESOURCE; -#endif } _pqos_api_unlock(); @@ -257,8 +317,7 @@ } int -pqos_alloc_release(const unsigned *core_array, - const unsigned core_num) +pqos_alloc_release(const unsigned *core_array, const unsigned core_num) { int ret; @@ -308,7 +367,7 @@ } if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task association!\n"); _pqos_api_unlock(); @@ -328,8 +387,7 @@ } int -pqos_alloc_release_pid(const pid_t *task_array, - const unsigned task_num) +pqos_alloc_release_pid(const pid_t *task_array, const unsigned task_num) { int ret; @@ -345,7 +403,7 @@ } if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task association!\n"); _pqos_api_unlock(); @@ -386,8 +444,7 @@ return PQOS_RETVAL_PARAM; } - if (mba_cfg != PQOS_MBA_ANY && - mba_cfg != PQOS_MBA_DEFAULT && + if (mba_cfg != PQOS_MBA_ANY && mba_cfg != PQOS_MBA_DEFAULT && mba_cfg != PQOS_MBA_CTRL) { LOG_ERROR("Unrecognized MBA configuration setting %d!\n", mba_cfg); @@ -427,7 +484,7 @@ return NULL; if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task association!\n"); return NULL; @@ -486,7 +543,7 @@ while ((bitmask & 1) != 0) /**< Shift until 0 found at position 0 */ bitmask >>= 1; - return (bitmask) ? 0 : 1; /**< non-zero bitmask is not contiguous */ + return (bitmask) ? 0 : 1; /**< non-zero bitmask is not contiguous */ } int @@ -516,7 +573,7 @@ if (ca[i].cdp) { is_contig = is_contiguous(ca[i].u.s.data_mask) && - is_contiguous(ca[i].u.s.code_mask); + is_contiguous(ca[i].u.s.code_mask); } else is_contig = is_contiguous(ca[i].u.ways_mask); @@ -641,7 +698,7 @@ if (ca[i].cdp) { is_contig = is_contiguous(ca[i].u.s.data_mask) && - is_contiguous(ca[i].u.s.code_mask); + is_contiguous(ca[i].u.s.code_mask); } else is_contig = is_contiguous(ca[i].u.ways_mask); @@ -751,41 +808,41 @@ if (requested == NULL || num_cos == 0) return PQOS_RETVAL_PARAM; + _pqos_api_lock(); + + ret = _pqos_check_init(1); + if (ret != PQOS_RETVAL_OK) { + _pqos_api_unlock(); + return ret; + } + /** * Check if MBA rate is within allowed range */ - for (i = 0; i < num_cos; i++) + for (i = 0; i < num_cos; i++) { + const struct cpuinfo_config *vconfig; + + cpuinfo_get_config(&vconfig); if (requested[i].ctrl == 0 && (requested[i].mb_max == 0 || - requested[i].mb_max > PQOS_MBA_LINEAR_MAX)) { + requested[i].mb_max > vconfig->mba_max)) { LOG_ERROR("MBA COS%u rate out of range (from 1-%d)!\n", - requested[i].class_id, PQOS_MBA_LINEAR_MAX); + requested[i].class_id, vconfig->mba_max); + _pqos_api_unlock(); return PQOS_RETVAL_PARAM; } - - _pqos_api_lock(); - - ret = _pqos_check_init(1); - if (ret != PQOS_RETVAL_OK) { - _pqos_api_unlock(); - return ret; } - if (m_interface == PQOS_INTER_MSR) - ret = hw_mba_set(mba_id, num_cos, requested, actual); + if (api.mba_set != NULL) + ret = api.mba_set(mba_id, num_cos, requested, actual); else { -#ifdef __linux__ - ret = os_mba_set(mba_id, num_cos, requested, actual); -#else - LOG_INFO("OS interface not supported!\n"); + LOG_INFO("Interface not supported!\n"); ret = PQOS_RETVAL_RESOURCE; -#endif } _pqos_api_unlock(); return ret; - } int @@ -807,15 +864,11 @@ return ret; } - if (m_interface == PQOS_INTER_MSR) - ret = hw_mba_get(mba_id, max_num_cos, num_cos, mba_tab); + if (api.mba_get != NULL) + ret = api.mba_get(mba_id, max_num_cos, num_cos, mba_tab); else { -#ifdef __linux__ - ret = os_mba_get(mba_id, max_num_cos, num_cos, mba_tab); -#else - LOG_INFO("OS interface not supported!\n"); + LOG_INFO("Interface not supported!\n"); ret = PQOS_RETVAL_RESOURCE; -#endif } _pqos_api_unlock(); @@ -859,8 +912,7 @@ } int -pqos_mon_assoc_get(const unsigned lcore, - pqos_rmid_t *rmid) +pqos_mon_assoc_get(const unsigned lcore, pqos_rmid_t *rmid) { int ret; @@ -922,18 +974,27 @@ return ret; } - if (m_interface == PQOS_INTER_MSR) - ret = hw_mon_start(num_cores, cores, event, context, group); + memset(group, 0, sizeof(*group)); + group->intl = + (struct pqos_mon_data_internal *)malloc(sizeof(*group->intl)); + if (group->intl == NULL) { + ret = PQOS_RETVAL_RESOURCE; + goto pqos_mon_start_exit; + } + memset(group->intl, 0, sizeof(*group->intl)); + + if (api.mon_start != NULL) + ret = api.mon_start(num_cores, cores, event, context, group); else { -#ifdef __linux__ - ret = os_mon_start(num_cores, cores, event, context, group); -#else - LOG_INFO("OS interface not supported!\n"); + LOG_INFO("Interface not supported!\n"); ret = PQOS_RETVAL_RESOURCE; -#endif } + +pqos_mon_start_exit: if (ret == PQOS_RETVAL_OK) group->valid = GROUP_VALID_MARKER; + else if (group->intl != NULL) + free(group->intl); _pqos_api_unlock(); @@ -959,24 +1020,24 @@ return ret; } - if (m_interface == PQOS_INTER_MSR) - ret = hw_mon_stop(group); + if (api.mon_stop != NULL) + ret = api.mon_stop(group); else { -#ifdef __linux__ - ret = os_mon_stop(group); -#else - LOG_INFO("OS interface not supported!\n"); + LOG_INFO("Interface not supported!\n"); ret = PQOS_RETVAL_RESOURCE; -#endif } + + free(group->intl); + group->intl = NULL; + group->valid = 0; + _pqos_api_unlock(); return ret; } int -pqos_mon_poll(struct pqos_mon_data **groups, - const unsigned num_groups) +pqos_mon_poll(struct pqos_mon_data **groups, const unsigned num_groups) { int ret; unsigned i; @@ -989,6 +1050,8 @@ return PQOS_RETVAL_PARAM; if (groups[i]->valid != GROUP_VALID_MARKER) return PQOS_RETVAL_PARAM; + if (groups[i]->event == 0) + return PQOS_RETVAL_PARAM; } _pqos_api_lock(); @@ -999,15 +1062,12 @@ return ret; } - if (m_interface == PQOS_INTER_MSR) - ret = hw_mon_poll(groups, num_groups); - else { -#ifdef __linux__ - ret = os_mon_poll(groups, num_groups); -#else - LOG_INFO("OS interface not supported!\n"); - ret = PQOS_RETVAL_RESOURCE; -#endif + for (i = 0; i < num_groups; i++) { + int ret = pqos_mon_poll_events(groups[i]); + + if (ret != PQOS_RETVAL_OK) + LOG_WARN("Failed to poll event on group number %u\n", + i); } _pqos_api_unlock(); @@ -1039,7 +1099,7 @@ return PQOS_RETVAL_PARAM; if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task monitoring!\n"); return PQOS_RETVAL_ERROR; @@ -1068,25 +1128,36 @@ return ret; } -#ifdef __linux__ - ret = os_mon_start_pids(num_pids, pids, event, context, group); -#else - UNUSED_PARAM(context); - LOG_INFO("OS interface not supported!\n"); - ret = PQOS_RETVAL_RESOURCE; -#endif + memset(group, 0, sizeof(*group)); + group->intl = malloc(sizeof(*group->intl)); + if (group->intl == NULL) { + ret = PQOS_RETVAL_RESOURCE; + goto pqos_mon_start_pids_exit; + } + memset(group->intl, 0, sizeof(*group->intl)); + + if (api.mon_start_pids != NULL) + ret = api.mon_start_pids(num_pids, pids, event, context, group); + else { + LOG_INFO("Interface not supported!\n"); + ret = PQOS_RETVAL_RESOURCE; + } +pqos_mon_start_pids_exit: if (ret == PQOS_RETVAL_OK) group->valid = GROUP_VALID_MARKER; + else if (group->intl != NULL) + free(group->intl); _pqos_api_unlock(); return ret; } -int pqos_mon_add_pids(const unsigned num_pids, - const pid_t *pids, - struct pqos_mon_data *group) +int +pqos_mon_add_pids(const unsigned num_pids, + const pid_t *pids, + struct pqos_mon_data *group) { int ret; @@ -1097,7 +1168,7 @@ return PQOS_RETVAL_PARAM; if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task monitoring!\n"); return PQOS_RETVAL_ERROR; @@ -1123,9 +1194,10 @@ return ret; } -int pqos_mon_remove_pids(const unsigned num_pids, - const pid_t *pids, - struct pqos_mon_data *group) +int +pqos_mon_remove_pids(const unsigned num_pids, + const pid_t *pids, + struct pqos_mon_data *group) { int ret; @@ -1136,7 +1208,7 @@ return PQOS_RETVAL_PARAM; if (m_interface != PQOS_INTER_OS && - m_interface != PQOS_INTER_OS_RESCTRL_MON) { + m_interface != PQOS_INTER_OS_RESCTRL_MON) { LOG_ERROR("Incompatible interface " "selected for task monitoring!\n"); return PQOS_RETVAL_ERROR; diff -Nru intel-cmt-cat-3.2/lib/api_doxygen.cfg intel-cmt-cat-4.0/lib/api_doxygen.cfg --- intel-cmt-cat-3.2/lib/api_doxygen.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/api_doxygen.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ # # BSD LICENSE # -# Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/api.h intel-cmt-cat-4.0/lib/api.h --- intel-cmt-cat-3.2/lib/api.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/api.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,19 +39,21 @@ extern "C" { #endif +#include "pqos.h" + /** * @brief Initializes api module * - * @param interface option, MSR or OS + * @param[in] interface option, MSR or OS + * @param[in] vendor CPU vendor * * @return Operational status * @retval PQOS_RETVAL_OK success */ -int api_init(int interface); +int api_init(int interface, enum pqos_vendor vendor); #ifdef __cplusplus } #endif #endif /* API_H */ - diff -Nru intel-cmt-cat-3.2/lib/cap.c intel-cmt-cat-4.0/lib/cap.c --- intel-cmt-cat-3.2/lib/cap.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/cap.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@ * * Capability functions: * - monitoring detection, this is to discover all monitoring event types. - * LLC occupancy is only supported now. * - LLC allocation detection, this is to discover last level cache * allocation feature. * - A new targeted function has to be implemented to discover new allocation @@ -54,19 +53,16 @@ #include #include -#include /* O_CREAT */ -#include /* usleep(), lockf() */ -#include /* S_Ixxx */ +#include /* O_CREAT */ +#include /* usleep(), lockf() */ +#include /* S_Ixxx */ #include -#include "pqos.h" - #include "cap.h" #include "os_cap.h" +#include "hw_cap.h" #include "allocation.h" #include "monitoring.h" - -#include "cpu_registers.h" #include "cpuinfo.h" #include "machine.h" #include "types.h" @@ -74,7 +70,6 @@ #include "api.h" #include "utils.h" #include "resctrl.h" -#include "perf_monitoring.h" /** * --------------------------------------- @@ -82,7 +77,6 @@ * --------------------------------------- */ - #ifndef LOCKFILE #ifdef __linux__ #define LOCKFILE "/var/lock/libpqos" @@ -136,9 +130,7 @@ * 1 PQOS_INTER_OS * 2 PQOS_INTER_OS_RESCTRL_MON */ -#ifdef __linux__ -static int m_interface = PQOS_INTER_MSR; -#endif +static enum pqos_interface m_interface = PQOS_INTER_MSR; /** * --------------------------------------- * Functions for safe multi-threading @@ -250,628 +242,45 @@ return PQOS_RETVAL_OK; } -/* - * ======================================= - * ======================================= - * - * Capability discovery routines - * - * ======================================= - * ======================================= - */ - /** - * @brief Retrieves cache size and number of ways - * - * Retrieves information about cache from \a cache_info structure. + * @brief Discovers support of L3 CAT * - * @param cache_info cache information structure - * @param num_ways place to store number of cache ways - * @param size place to store cache size in bytes + * @param[out] r_cap place to store L3 CAT capabilities structure + * @param[in] cpu detected cpu topology + * @param[in] iface Selected interface * * @return Operation status * @retval PQOS_RETVAL_OK success - * @retval PQOS_RETVAL_PARAM incorrect parameters - * @retval PQOS_RETVAL_RESOURCE cache not detected */ static int -get_cache_info(const struct pqos_cacheinfo *cache_info, - unsigned *num_ways, - unsigned *size) +cap_l3ca_discover(struct pqos_cap_l3ca **r_cap, + const struct pqos_cpuinfo *cpu, + const enum pqos_interface iface) { - if (num_ways == NULL && size == NULL) - return PQOS_RETVAL_PARAM; - if (cache_info == NULL) - return PQOS_RETVAL_PARAM; - if (!cache_info->detected) - return PQOS_RETVAL_RESOURCE; - if (num_ways != NULL) - *num_ways = cache_info->num_ways; - if (size != NULL) - *size = cache_info->total_size; - return PQOS_RETVAL_OK; -} - -/** - * @brief Adds new event type to \a mon monitoring structure - * - * @param mon Monitoring structure which is to be updated with the new - * event type - * @param res_id resource id - * @param event_type event type - * @param max_rmid max RMID for the event - * @param scale_factor event specific scale factor - * @param max_num_events maximum number of events that \a mon can accommodate - */ -static void -add_monitoring_event(struct pqos_cap_mon *mon, - const unsigned res_id, - const int event_type, - const unsigned max_rmid, - const uint32_t scale_factor, - const unsigned max_num_events) -{ - if (mon->num_events >= max_num_events) { - LOG_WARN("%s() no space for event type %d (resource id %u)!\n", - __func__, event_type, res_id); - return; - } - - LOG_DEBUG("Adding monitoring event: resource ID %u, " - "type %d to table index %u\n", - res_id, event_type, mon->num_events); - - mon->events[mon->num_events].type = (enum pqos_mon_event) event_type; - mon->events[mon->num_events].max_rmid = max_rmid; - mon->events[mon->num_events].scale_factor = scale_factor; - mon->num_events++; -} - -/** - * @brief Discovers monitoring capabilities - * - * Runs series of CPUID instructions to discover system CMT - * capabilities. - * Allocates memory for monitoring structure and - * returns it through \a r_mon to the caller. - * - * @param r_mon place to store created monitoring structure - * @param cpu CPU topology structure - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - * @retval PQOS_RETVAL_RESOURCE monitoring not supported - * @retval PQOS_RETVAL_ERROR enumeration error - */ -static int -discover_monitoring(struct pqos_cap_mon **r_mon, - const struct pqos_cpuinfo *cpu) -{ - struct cpuid_out res, cpuid_0xa; - struct cpuid_out cpuid_0xf_1; - int ret = PQOS_RETVAL_OK; - unsigned sz = 0, max_rmid = 0, - l3_size = 0, num_events = 0; - struct pqos_cap_mon *mon = NULL; - - ASSERT(r_mon != NULL && cpu != NULL); - - /** - * Run CPUID.0x7.0 to check - * for quality monitoring capability (bit 12 of ebx) - */ - lcpuid(0x7, 0x0, &res); - if (!(res.ebx & (1 << 12))) { - LOG_WARN("CPUID.0x7.0: Monitoring capability not supported!\n"); - return PQOS_RETVAL_RESOURCE; - } - - /** - * We can go to CPUID.0xf.0 for further - * exploration of monitoring capabilities - */ - lcpuid(0xf, 0x0, &res); - if (!(res.edx & (1 << 1))) { - LOG_WARN("CPUID.0xf.0: Monitoring capability not supported!\n"); - return PQOS_RETVAL_RESOURCE; - } - - /** - * MAX_RMID for the socket - */ - max_rmid = (unsigned) res.ebx + 1; - ret = get_cache_info(&cpu->l3, NULL, &l3_size); /**< L3 cache size */ - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("Error reading L3 information!\n"); - return PQOS_RETVAL_ERROR; - } - - /** - * Check number of monitoring events to allocate memory for - * Sub-leaf 1 provides information on monitoring. - */ - lcpuid(0xf, 1, &cpuid_0xf_1); /**< query resource monitoring */ - - if (cpuid_0xf_1.edx & 1) - num_events++; /**< LLC occupancy */ - if (cpuid_0xf_1.edx & 2) - num_events++; /**< total memory bandwidth event */ - if (cpuid_0xf_1.edx & 4) - num_events++; /**< local memory bandwidth event */ - if ((cpuid_0xf_1.edx & 2) && (cpuid_0xf_1.edx & 4)) - num_events++; /**< remote memory bandwidth virtual event */ - - if (!num_events) - return PQOS_RETVAL_ERROR; - - /** - * Check if IPC can be calculated & supported - */ - lcpuid(0xa, 0x0, &cpuid_0xa); - if (((cpuid_0xa.ebx & 3) == 0) && ((cpuid_0xa.edx & 31) > 1)) - num_events++; - - /** - * This means we can program LLC misses too - */ - if (((cpuid_0xa.eax >> 8) & 0xff) > 1) - num_events++; - - /** - * Allocate memory for detected events and - * fill the events in. - */ - sz = (num_events * sizeof(struct pqos_monitor)) + sizeof(*mon); - mon = (struct pqos_cap_mon *) malloc(sz); - if (mon == NULL) - return PQOS_RETVAL_RESOURCE; - - memset(mon, 0, sz); - mon->mem_size = sz; - mon->max_rmid = max_rmid; - mon->l3_size = l3_size; - - if (cpuid_0xf_1.edx & 1) - add_monitoring_event(mon, 1, PQOS_MON_EVENT_L3_OCCUP, - cpuid_0xf_1.ecx + 1, cpuid_0xf_1.ebx, - num_events); - if (cpuid_0xf_1.edx & 2) - add_monitoring_event(mon, 1, PQOS_MON_EVENT_TMEM_BW, - cpuid_0xf_1.ecx + 1, cpuid_0xf_1.ebx, - num_events); - if (cpuid_0xf_1.edx & 4) - add_monitoring_event(mon, 1, PQOS_MON_EVENT_LMEM_BW, - cpuid_0xf_1.ecx + 1, cpuid_0xf_1.ebx, - num_events); - - if ((cpuid_0xf_1.edx & 2) && (cpuid_0xf_1.edx & 4)) - add_monitoring_event(mon, 1, PQOS_MON_EVENT_RMEM_BW, - cpuid_0xf_1.ecx + 1, cpuid_0xf_1.ebx, - num_events); - - if (((cpuid_0xa.ebx & 3) == 0) && ((cpuid_0xa.edx & 31) > 1)) - add_monitoring_event(mon, 0, PQOS_PERF_EVENT_IPC, - 0, 0, num_events); - - if (((cpuid_0xa.eax >> 8) & 0xff) > 1) - add_monitoring_event(mon, 0, PQOS_PERF_EVENT_LLC_MISS, - 0, 0, num_events); - - (*r_mon) = mon; - return PQOS_RETVAL_OK; -} - -/** - * @brief Checks L3 CDP enable status across all CPU sockets - * - * It also validates if L3 CDP enabling is consistent across - * CPU sockets. - * At the moment, such scenario is considered as error - * that requires CAT reset. - * - * @param cpu detected CPU topology - * @param enabled place to store L3 CDP enabling status - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -static int -l3cdp_is_enabled(const struct pqos_cpuinfo *cpu, - int *enabled) -{ - unsigned *l3cat_ids = NULL; - unsigned l3cat_id_num = 0, j = 0; - unsigned enabled_num = 0, disabled_num = 0; - int ret = PQOS_RETVAL_OK; - - ASSERT(enabled != NULL && cpu != NULL); - if (enabled == NULL || cpu == NULL) - return PQOS_RETVAL_PARAM; - - *enabled = 0; - - /** - * Get list of l3cat id's - */ - l3cat_ids = pqos_cpu_get_l3cat_ids(cpu, &l3cat_id_num); - if (l3cat_ids == NULL) - return PQOS_RETVAL_RESOURCE; - - for (j = 0; j < l3cat_id_num; j++) { - uint64_t reg = 0; - unsigned core = 0; - - ret = pqos_cpu_get_one_by_l3cat_id(cpu, l3cat_ids[j], &core); - if (ret != PQOS_RETVAL_OK) - goto l3cdp_is_enabled_exit; - - if (msr_read(core, PQOS_MSR_L3_QOS_CFG, ®) != - MACHINE_RETVAL_OK) { - ret = PQOS_RETVAL_ERROR; - goto l3cdp_is_enabled_exit; - } - - if (reg & PQOS_MSR_L3_QOS_CFG_CDP_EN) - enabled_num++; - else - disabled_num++; - } - - if (disabled_num > 0 && enabled_num > 0) { - LOG_ERROR("Inconsistent L3 CDP settings across l3cat_ids." - "Please reset CAT or reboot your system!\n"); - ret = PQOS_RETVAL_ERROR; - goto l3cdp_is_enabled_exit; - } - - if (enabled_num > 0) - *enabled = 1; - - LOG_INFO("L3 CDP is %s\n", (*enabled) ? "enabled" : "disabled"); - - l3cdp_is_enabled_exit: - if (l3cat_ids != NULL) - free(l3cat_ids); - - return ret; -} - -/** - * @brief Checks L2 CDP enable status across all CPU clusters - * - * It also validates if L2 CDP enabling is consistent across - * CPU clusters. - * At the moment, such scenario is considered as error - * that requires CAT reset. - * - * @param cpu detected CPU topology - * @param enabled place to store L2 CDP enabling status - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -static int -l2cdp_is_enabled(const struct pqos_cpuinfo *cpu, int *enabled) -{ - unsigned *l2ids = NULL; - unsigned l2id_num = 0; - unsigned enabled_num = 0, disabled_num = 0; - unsigned i; - int ret = PQOS_RETVAL_OK; - - /** - * Get list of L2 clusters id's - */ - l2ids = pqos_cpu_get_l2ids(cpu, &l2id_num); - if (l2ids == NULL || l2id_num == 0) { - ret = PQOS_RETVAL_RESOURCE; - goto l2cdp_is_enabled_exit; - } - - for (i = 0; i < l2id_num; i++) { - uint64_t reg = 0; - unsigned core = 0; - - ret = pqos_cpu_get_one_by_l2id(cpu, l2ids[i], &core); - if (ret != PQOS_RETVAL_OK) - goto l2cdp_is_enabled_exit; - - if (msr_read(core, PQOS_MSR_L2_QOS_CFG, ®) != - MACHINE_RETVAL_OK) { - ret = PQOS_RETVAL_ERROR; - goto l2cdp_is_enabled_exit; - } - - if (reg & PQOS_MSR_L2_QOS_CFG_CDP_EN) - enabled_num++; - else - disabled_num++; - } - - if (disabled_num > 0 && enabled_num > 0) { - LOG_ERROR("Inconsistent L2 CDP settings across clusters." - "Please reset CAT or reboot your system!\n"); - ret = PQOS_RETVAL_ERROR; - goto l2cdp_is_enabled_exit; - } - - if (enabled_num > 0) - *enabled = 1; - - LOG_INFO("L2 CDP is %s\n", (*enabled) ? "enabled" : "disabled"); - - l2cdp_is_enabled_exit: - if (l2ids != NULL) - free(l2ids); - - return ret; -} - -/** - * @brief Detects presence of L3 CAT based on register probing. - * - * This method of detecting CAT does the following steps. - * - probe COS registers one by one and exit on first error - * - if procedure fails on COS0 then CAT is not supported - * - use CPUID.0x4.0x3 to get number of cache ways - * - * @param cap CAT structure to be initialized - * @param cpu CPU topology structure - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - * @retval PQOS_RETVAL_PARAM invalid input configuration/parameters - * @retval PQOS_RETVAL_RESOURCE technology not supported - */ -static int -discover_alloc_l3_probe(struct pqos_cap_l3ca *cap, - const struct pqos_cpuinfo *cpu) -{ - unsigned i = 0, lcore; - const unsigned max_classes = - PQOS_MSR_L3CA_MASK_END - PQOS_MSR_L3CA_MASK_START + 1; - - ASSERT(cap != NULL && cpu != NULL); - - /** - * Pick a valid core and run series of MSR reads on it - */ - lcore = cpu->cores[0].lcore; - for (i = 0; i < max_classes; i++) { - int msr_ret; - uint64_t value; - - msr_ret = msr_read(lcore, PQOS_MSR_L3CA_MASK_START + i, &value); - if (msr_ret != MACHINE_RETVAL_OK) - break; - } - - if (i == 0) { - LOG_WARN("Error probing COS0 on core %u\n", lcore); - return PQOS_RETVAL_RESOURCE; - } - - /** - * Number of ways and CBM is detected with CPUID.0x4.0x3 later on - */ - cap->num_classes = i; - return PQOS_RETVAL_OK; -} - -/** - * @brief Detects presence of L3 CAT based on brand string. - * - * If CPUID.0x7.0 doesn't report CAT feature - * platform may still support it: - * - we need to check brand string vs known ones - * - use CPUID.0x4.0x3 to get number of cache ways - * - * @param cap CAT structure to be initialized - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - * @retval PQOS_RETVAL_RESOURCE technology not supported - */ -static int -discover_alloc_l3_brandstr(struct pqos_cap_l3ca *cap) -{ -#define CPUID_LEAF_BRAND_START 0x80000002UL -#define CPUID_LEAF_BRAND_END 0x80000004UL -#define CPUID_LEAF_BRAND_NUM (CPUID_LEAF_BRAND_END-CPUID_LEAF_BRAND_START+1) -#define MAX_BRAND_STRING_LEN (CPUID_LEAF_BRAND_NUM*4*sizeof(uint32_t)) - static const char * const supported_brands[] = { - "E5-2658 v3", - "E5-2648L v3", "E5-2628L v3", - "E5-2618L v3", "E5-2608L v3", - "E5-2658A v3", "E3-1258L v4", - "E3-1278L v4" - }; - struct cpuid_out res; - int ret = PQOS_RETVAL_OK, - match_found = 0; - uint32_t brand[MAX_BRAND_STRING_LEN / 4 + 1]; - char *brand_str = (char *)brand; - uint32_t *brand_u32 = brand; - unsigned i = 0; - - /** - * Assume \a cap is not NULL at this stage. - * Adequate check has to be done in the caller. - */ - ASSERT(cap != NULL); - - lcpuid(0x80000000, 0, &res); - if (res.eax < CPUID_LEAF_BRAND_END) { - LOG_ERROR("Brand string CPU-ID extended functions " - "not supported\n"); - return PQOS_RETVAL_ERROR; - } - - memset(brand, 0, sizeof(brand)); - - for (i = 0; i < CPUID_LEAF_BRAND_NUM; i++) { - lcpuid((unsigned)CPUID_LEAF_BRAND_START + i, 0, &res); - *brand_u32++ = res.eax; - *brand_u32++ = res.ebx; - *brand_u32++ = res.ecx; - *brand_u32++ = res.edx; - } - - LOG_DEBUG("CPU brand string '%s'\n", brand_str); - - /** - * match brand against supported ones - */ - for (i = 0; i < DIM(supported_brands); i++) - if (strstr(brand_str, supported_brands[i]) != NULL) { - LOG_INFO("Cache allocation detected for model name " - "'%s'\n", brand_str); - match_found = 1; - break; - } - - if (!match_found) { - LOG_WARN("Cache allocation not supported on model name '%s'!\n", - brand_str); - return PQOS_RETVAL_RESOURCE; - } - - /** - * Figure out number of ways and CBM (1:1) - * using CPUID.0x4.0x3 - */ - cap->num_classes = 4; - - return ret; -} - -/** - * @brief Detects presence of L3 CAT based on CPUID - * - * @param cap CAT structure to be initialized - * @param cpu CPU topology structure - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - * @retval PQOS_RETVAL_RESOURCE technology not supported - */ -static int -discover_alloc_l3_cpuid(struct pqos_cap_l3ca *cap, - const struct pqos_cpuinfo *cpu) -{ - struct cpuid_out res; - int ret = PQOS_RETVAL_OK; - - /** - * We can go to CPUID.0x10.0 to explore - * allocation capabilities - */ - lcpuid(0x10, 0x0, &res); - if (!(res.ebx & (1 << PQOS_RES_ID_L3_ALLOCATION))) { - LOG_INFO("CPUID.0x10.0: L3 CAT not detected.\n"); - return PQOS_RETVAL_RESOURCE; - } - - /** - * L3 CAT detected - * - get more info about it - */ - lcpuid(0x10, PQOS_RES_ID_L3_ALLOCATION, &res); - cap->num_classes = res.edx + 1; - cap->num_ways = res.eax + 1; - cap->cdp = (res.ecx >> PQOS_CPUID_CAT_CDP_BIT) & 1; - cap->cdp_on = 0; - cap->way_contention = (uint64_t) res.ebx; - - if (cap->cdp) { - /** - * CDP is supported but is it on? - */ - int cdp_on = 0; - - ret = l3cdp_is_enabled(cpu, &cdp_on); - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("L3 CDP detection error!\n"); - return ret; - } - cap->cdp_on = cdp_on; - if (cdp_on) - cap->num_classes = cap->num_classes / 2; - } - - return ret; -} - -/** - * @brief Discovers L3 CAT - * - * First it tries to detects CAT through CPUID.0x7.0 - * if this fails then falls into brand string check. - * - * Function allocates memory for CAT capabilities - * and returns it to the caller through \a r_cap. - * - * \a cpu is only needed to detect CDP status. - * - * @param r_cap place to store CAT capabilities structure - * @param cpu detected cpu topology - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - */ -static int -discover_alloc_l3(struct pqos_cap_l3ca **r_cap, - const struct pqos_cpuinfo *cpu) -{ - struct cpuid_out res; struct pqos_cap_l3ca *cap = NULL; - const unsigned sz = sizeof(*cap); - unsigned l3_size = 0; - int ret = PQOS_RETVAL_OK; + int ret; - cap = (struct pqos_cap_l3ca *)malloc(sz); + cap = (struct pqos_cap_l3ca *)malloc(sizeof(*cap)); if (cap == NULL) return PQOS_RETVAL_RESOURCE; - ASSERT(cap != NULL); - - memset(cap, 0, sz); - cap->mem_size = sz; - - /** - * Run CPUID.0x7.0 to check - * for allocation capability (bit 15 of ebx) - */ - lcpuid(0x7, 0x0, &res); - - if (res.ebx & (1 << 15)) { - /** - * Use CPUID method - */ - LOG_INFO("CPUID.0x7.0: L3 CAT supported\n"); - ret = discover_alloc_l3_cpuid(cap, cpu); - if (ret == PQOS_RETVAL_OK) - ret = get_cache_info(&cpu->l3, NULL, &l3_size); - } else { - /** - * Use brand string matching method 1st. - * If it fails then try register probing. - */ - LOG_INFO("CPUID.0x7.0: L3 CAT not detected. " - "Checking brand string...\n"); - ret = discover_alloc_l3_brandstr(cap); - if (ret != PQOS_RETVAL_OK) - ret = discover_alloc_l3_probe(cap, cpu); - if (ret == PQOS_RETVAL_OK) - ret = get_cache_info(&cpu->l3, &cap->num_ways, - &l3_size); + switch (iface) { + case PQOS_INTER_MSR: + ret = hw_cap_l3ca_discover(cap, cpu); + break; +#ifdef __linux__ + case PQOS_INTER_OS: + case PQOS_INTER_OS_RESCTRL_MON: + ret = os_cap_l3ca_discover(cap, cpu); + break; +#endif + default: + ret = PQOS_RETVAL_RESOURCE; + break; } - if (cap->num_ways > 0) - cap->way_size = l3_size / cap->num_ways; - if (ret == PQOS_RETVAL_OK) - (*r_cap) = cap; + *r_cap = cap; else free(cap); @@ -879,156 +288,95 @@ } /** - * @brief Discovers L2 CAT + * @brief Discovers support of L2 CAT * - * @param r_cap place to store L2 CAT capabilities structure - * @param cpu CPU topology structure + * @param[out] r_cap place to store L2 CAT capabilities structure + * @param[in] cpu detected cpu topology + * @param[in] iface Selected interface * * @return Operation status * @retval PQOS_RETVAL_OK success */ static int -discover_alloc_l2(struct pqos_cap_l2ca **r_cap, - const struct pqos_cpuinfo *cpu) +cap_l2ca_discover(struct pqos_cap_l2ca **r_cap, + const struct pqos_cpuinfo *cpu, + const enum pqos_interface iface) { - struct cpuid_out res; struct pqos_cap_l2ca *cap = NULL; - const unsigned sz = sizeof(*cap); - unsigned l2_size = 0; - int ret = PQOS_RETVAL_OK; - - ASSERT(cpu != NULL); + int ret; - cap = (struct pqos_cap_l2ca *)malloc(sz); + cap = (struct pqos_cap_l2ca *)malloc(sizeof(*cap)); if (cap == NULL) return PQOS_RETVAL_RESOURCE; - ASSERT(cap != NULL); - - memset(cap, 0, sz); - cap->mem_size = sz; - - /** - * Run CPUID.0x7.0 to check - * for allocation capability (bit 15 of ebx) - */ - lcpuid(0x7, 0x0, &res); - if (!(res.ebx & (1 << 15))) { - LOG_INFO("CPUID.0x7.0: L2 CAT not supported\n"); - free(cap); - return PQOS_RETVAL_RESOURCE; - } - - /** - * We can go to CPUID.0x10.0 to obtain more info - */ - lcpuid(0x10, 0x0, &res); - if (!(res.ebx & (1 << PQOS_RES_ID_L2_ALLOCATION))) { - LOG_INFO("CPUID 0x10.0: L2 CAT not supported!\n"); - free(cap); - return PQOS_RETVAL_RESOURCE; - } - - lcpuid(0x10, PQOS_RES_ID_L2_ALLOCATION, &res); - - cap->num_classes = res.edx+1; - cap->num_ways = res.eax+1; - cap->cdp = (res.ecx >> PQOS_CPUID_CAT_CDP_BIT) & 1; - cap->cdp_on = 0; - cap->way_contention = (uint64_t) res.ebx; - - if (cap->cdp) { - int cdp_on = 0; - - /* - * Check if L2 CDP is enabled - */ - ret = l2cdp_is_enabled(cpu, &cdp_on); - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("L2 CDP detection error!\n"); - free(cap); - return ret; - } - cap->cdp_on = cdp_on; - if (cdp_on) - cap->num_classes = cap->num_classes / 2; + switch (iface) { + case PQOS_INTER_MSR: + ret = hw_cap_l2ca_discover(cap, cpu); + break; +#ifdef __linux__ + case PQOS_INTER_OS: + case PQOS_INTER_OS_RESCTRL_MON: + ret = os_cap_l2ca_discover(cap, cpu); + break; +#endif + default: + ret = PQOS_RETVAL_RESOURCE; + break; } - ret = get_cache_info(&cpu->l2, NULL, &l2_size); - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("Error reading L2 info!\n"); + if (ret == PQOS_RETVAL_OK) + *r_cap = cap; + else free(cap); - return PQOS_RETVAL_ERROR; - } - if (cap->num_ways > 0) - cap->way_size = l2_size / cap->num_ways; - (*r_cap) = cap; return ret; } /** - * @brief Discovers MBA + * @brief Discovers support of MBA * - * @param r_cap place to store MBA capabilities structure + * @param[out] r_cap place to store MBA capabilities structure + * @param[in] cpu detected cpu topology + * @param[in] iface Selected interface * * @return Operation status * @retval PQOS_RETVAL_OK success */ static int -discover_alloc_mba(struct pqos_cap_mba **r_cap) +cap_mba_discover(struct pqos_cap_mba **r_cap, + const struct pqos_cpuinfo *cpu, + const enum pqos_interface iface) { - struct cpuid_out res; struct pqos_cap_mba *cap = NULL; - const unsigned sz = sizeof(*cap); - int ret = PQOS_RETVAL_OK; + int ret; - cap = (struct pqos_cap_mba *)malloc(sz); + cap = (struct pqos_cap_mba *)malloc(sizeof(*cap)); if (cap == NULL) return PQOS_RETVAL_RESOURCE; - ASSERT(cap != NULL); - - memset(cap, 0, sz); - cap->mem_size = sz; - cap->ctrl = -1; - cap->ctrl_on = 0; - - /** - * Run CPUID.0x7.0 to check - * for allocation capability (bit 15 of ebx) - */ - lcpuid(0x7, 0x0, &res); - if (!(res.ebx & (1 << 15))) { - LOG_INFO("CPUID.0x7.0: MBA not supported\n"); - free(cap); - return PQOS_RETVAL_RESOURCE; - } - - /** - * We can go to CPUID.0x10.0 to obtain more info - */ - lcpuid(0x10, 0x0, &res); - if (!(res.ebx & (1 << PQOS_RES_ID_MB_ALLOCATION))) { - LOG_INFO("CPUID 0x10.0: MBA not supported!\n"); - free(cap); - return PQOS_RETVAL_RESOURCE; - } - - lcpuid(0x10, PQOS_RES_ID_MB_ALLOCATION, &res); + switch (iface) { + case PQOS_INTER_MSR: + if (cpu->vendor == PQOS_VENDOR_AMD) + ret = amd_cap_mba_discover(cap, cpu); + else + ret = hw_cap_mba_discover(cap, cpu); + break; +#ifdef __linux__ + case PQOS_INTER_OS: + case PQOS_INTER_OS_RESCTRL_MON: + ret = os_cap_mba_discover(cap, cpu); + break; +#endif + default: + ret = PQOS_RETVAL_RESOURCE; + break; + } - cap->num_classes = (res.edx & 0xffff) + 1; - cap->throttle_max = (res.eax & 0xfff) + 1; - cap->is_linear = (res.ecx >> 2) & 1; - if (cap->is_linear) - cap->throttle_step = 100 - cap->throttle_max; - else { - LOG_WARN("MBA non-linear mode not supported yet!\n"); + if (ret == PQOS_RETVAL_OK) + *r_cap = cap; + else free(cap); - return PQOS_RETVAL_RESOURCE; - } - (*r_cap) = cap; return ret; } @@ -1059,7 +407,7 @@ * Monitoring init */ if (inter == PQOS_INTER_MSR) - ret = discover_monitoring(&det_mon, cpu); + ret = hw_cap_mon_discover(&det_mon, cpu); #ifdef __linux__ else if (inter == PQOS_INTER_OS || inter == PQOS_INTER_OS_RESCTRL_MON) ret = os_cap_mon_discover(&det_mon, cpu); @@ -1081,12 +429,7 @@ /** * L3 Cache allocation init */ - if (inter == PQOS_INTER_MSR) - ret = discover_alloc_l3(&det_l3ca, cpu); -#ifdef __linux__ - else if (inter == PQOS_INTER_OS || inter == PQOS_INTER_OS_RESCTRL_MON) - ret = os_cap_l3ca_discover(&det_l3ca, cpu); -#endif + ret = cap_l3ca_discover(&det_l3ca, cpu, inter); switch (ret) { case PQOS_RETVAL_OK: LOG_INFO("L3CA capability detected\n"); @@ -1113,12 +456,7 @@ /** * L2 Cache allocation init */ - if (inter == PQOS_INTER_MSR) - ret = discover_alloc_l2(&det_l2ca, cpu); -#ifdef __linux__ - else if (inter == PQOS_INTER_OS || inter == PQOS_INTER_OS_RESCTRL_MON) - ret = os_cap_l2ca_discover(&det_l2ca, cpu); -#endif + ret = cap_l2ca_discover(&det_l2ca, cpu, inter); switch (ret) { case PQOS_RETVAL_OK: LOG_INFO("L2CA capability detected\n"); @@ -1128,7 +466,8 @@ det_l2ca->num_ways, (unsigned long)det_l2ca->way_contention); LOG_INFO("L2 CAT details: cache size %u bytes, way size %u " - "bytes\n", det_l2ca->way_size * det_l2ca->num_ways, + "bytes\n", + det_l2ca->way_size * det_l2ca->num_ways, det_l2ca->way_size); sz += sizeof(struct pqos_capability); break; @@ -1144,19 +483,13 @@ /** * Memory bandwidth allocation init */ - if (inter == PQOS_INTER_MSR) - ret = discover_alloc_mba(&det_mba); -#ifdef __linux__ - else if (inter == PQOS_INTER_OS || inter == PQOS_INTER_OS_RESCTRL_MON) - ret = os_cap_mba_discover(&det_mba, cpu); -#endif + ret = cap_mba_discover(&det_mba, cpu, inter); switch (ret) { case PQOS_RETVAL_OK: LOG_INFO("MBA capability detected\n"); LOG_INFO("MBA details: " "#COS=%u, %slinear, max=%u, step=%u\n", - det_mba->num_classes, - det_mba->is_linear ? "" : "non-", + det_mba->num_classes, det_mba->is_linear ? "" : "non-", det_mba->throttle_max, det_mba->throttle_step); sz += sizeof(struct pqos_capability); break; @@ -1227,10 +560,9 @@ #endif } - (*p_cap) = _cap; - error_exit: +error_exit: if (ret != PQOS_RETVAL_OK) { if (det_mon != NULL) free(det_mon); @@ -1280,22 +612,23 @@ if (environment != NULL) { if (strncasecmp(environment, "OS", 2) == 0) { if (config->interface != PQOS_INTER_OS) { - fprintf(stderr, "Interface initialization " - "error!\nYour system has been " - "restricted to use the OS interface " - "only!\n"); + fprintf(stderr, + "Interface initialization error!\n" + "Your system has been restricted " + "to use the OS interface only!\n"); return PQOS_RETVAL_ERROR; } } else if (strncasecmp(environment, "MSR", 3) == 0) { if (config->interface != PQOS_INTER_MSR) { - fprintf(stderr, "Interface initialization " - "error!\nYour system has been " - "restricted to use the MSR interface " - "only!\n"); + fprintf(stderr, + "Interface initialization error!\n" + "Your system has been restricted " + "to use the MSR interface only!\n"); return PQOS_RETVAL_ERROR; } } else { - fprintf(stderr, "Interface initialization error!\n" + fprintf(stderr, + "Interface initialization error!\n" "Invalid interface enforcement selection.\n"); return PQOS_RETVAL_ERROR; } @@ -1314,10 +647,8 @@ return ret; } - ret = log_init(config->fd_log, - config->callback_log, - config->context_log, - config->verbose); + ret = log_init(config->fd_log, config->callback_log, + config->context_log, config->verbose); if (ret != LOG_RETVAL_OK) { fprintf(stderr, "log_init() error\n"); goto init_error; @@ -1349,13 +680,13 @@ #ifdef __linux__ if (config->interface == PQOS_INTER_OS || - config->interface == PQOS_INTER_OS_RESCTRL_MON) { + config->interface == PQOS_INTER_OS_RESCTRL_MON) { ret = os_cap_init(config->interface); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("os_cap_init() error %d\n", ret); goto machine_init_error; } - } else if (access(RESCTRL_PATH"/cpus", F_OK) == 0) + } else if (access(RESCTRL_PATH "/cpus", F_OK) == 0) LOG_WARN("resctl filesystem mounted! Using MSR " "interface may corrupt resctrl filesystem " "and cause unexpected behaviour\n"); @@ -1373,14 +704,14 @@ goto machine_init_error; } - ret = api_init(config->interface); + ret = api_init(config->interface, m_cpu->vendor); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("_pqos_api_init() error %d\n", ret); goto machine_init_error; } -#ifdef __linux__ + m_interface = config->interface; -#endif + ret = pqos_alloc_init(m_cpu, m_cap, config); switch (ret) { case PQOS_RETVAL_BUSY: @@ -1422,16 +753,16 @@ ret = PQOS_RETVAL_ERROR; } - machine_init_error: +machine_init_error: if (ret != PQOS_RETVAL_OK) - (void) machine_fini(); - cpuinfo_init_error: + (void)machine_fini(); +cpuinfo_init_error: if (ret != PQOS_RETVAL_OK) - (void) cpuinfo_fini(); - log_init_error: + (void)cpuinfo_fini(); +log_init_error: if (ret != PQOS_RETVAL_OK) - (void) log_fini(); - init_error: + (void)log_fini(); +init_error: if (ret != PQOS_RETVAL_OK) { if (m_cap != NULL) { for (i = 0; i < m_cap->num_cap; i++) @@ -1516,8 +847,7 @@ */ int -pqos_cap_get(const struct pqos_cap **cap, - const struct pqos_cpuinfo **cpu) +pqos_cap_get(const struct pqos_cap **cap, const struct pqos_cpuinfo **cpu) { int ret = PQOS_RETVAL_OK; @@ -1542,6 +872,8 @@ _pqos_cap_l3cdp_change(const enum pqos_cdp_config cdp) { struct pqos_cap_l3ca *l3_cap = NULL; + struct pqos_cap_l3ca cap; + int ret; unsigned i; ASSERT(cdp == PQOS_REQUIRE_CDP_ON || cdp == PQOS_REQUIRE_CDP_OFF || @@ -1558,6 +890,26 @@ if (l3_cap == NULL) return; + switch (m_interface) { + case PQOS_INTER_MSR: + ret = hw_cap_l3ca_discover(&cap, m_cpu); + break; +#ifdef __linux__ + case PQOS_INTER_OS: /* fall through */ + case PQOS_INTER_OS_RESCTRL_MON: + ret = os_cap_l3ca_discover(&cap, m_cpu); + break; +#endif + default: + ret = PQOS_RETVAL_RESOURCE; + break; + } + + if (ret == PQOS_RETVAL_OK) { + *l3_cap = cap; + return; + } + if (cdp == PQOS_REQUIRE_CDP_ON && !l3_cap->cdp_on) { /* turn on */ l3_cap->cdp_on = 1; @@ -1575,7 +927,9 @@ _pqos_cap_l2cdp_change(const enum pqos_cdp_config cdp) { struct pqos_cap_l2ca *l2_cap = NULL; + struct pqos_cap_l2ca cap; unsigned i; + int ret; ASSERT(cdp == PQOS_REQUIRE_CDP_ON || cdp == PQOS_REQUIRE_CDP_OFF || cdp == PQOS_REQUIRE_CDP_ANY); @@ -1591,6 +945,26 @@ if (l2_cap == NULL) return; + switch (m_interface) { + case PQOS_INTER_MSR: + ret = hw_cap_l2ca_discover(&cap, m_cpu); + break; +#ifdef __linux__ + case PQOS_INTER_OS: + case PQOS_INTER_OS_RESCTRL_MON: + ret = os_cap_l2ca_discover(&cap, m_cpu); + break; +#endif + default: + ret = PQOS_RETVAL_RESOURCE; + break; + } + + if (ret == PQOS_RETVAL_OK) { + *l2_cap = cap; + return; + } + if (cdp == PQOS_REQUIRE_CDP_ON && !l2_cap->cdp_on) { /* turn on */ l2_cap->cdp_on = 1; @@ -1635,9 +1009,14 @@ } } +enum pqos_interface +_pqos_iface(void) +{ + return m_interface; +} + void -_pqos_cap_get(const struct pqos_cap **cap, - const struct pqos_cpuinfo **cpu) +_pqos_cap_get(const struct pqos_cap **cap, const struct pqos_cpuinfo **cpu) { if (cap != NULL) { ASSERT(m_cap != NULL); diff -Nru intel-cmt-cat-3.2/lib/cap.h intel-cmt-cat-4.0/lib/cap.h --- intel-cmt-cat-3.2/lib/cap.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/cap.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -100,6 +100,13 @@ int _pqos_check_init(const int expect); /** + * @brief Internal API to retrie PQoS interface + * + * @return PQoS interface + */ +enum pqos_interface _pqos_iface(void); + +/** * @brief Internal API to retrie PQoS capabilities data * * @param [out] cap location to store PQoS capabilities information at diff -Nru intel-cmt-cat-3.2/lib/common.c intel-cmt-cat-4.0/lib/common.c --- intel-cmt-cat-3.2/lib/common.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/common.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,69 +32,57 @@ * */ -#include -#include -#include -#include +#include +#include #include -#include #include "pqos.h" #include "common.h" #include "log.h" - -/** - * @brief Checks if a path to a file contains any symbolic links. - * - * @param [in] name a path to a file - * - * @return Operation status - * @retval PQOS_RETVAL_OK if the path exists and does not contain any - * symbolic links. - */ -static int -check_symlink(const char *name) +FILE * +pqos_fopen(const char *name, const char *mode) { int fd; - int oflag; - char *dir = strdup(name); - char *path = dir; - - if (dir == NULL) - return PQOS_RETVAL_ERROR; - - oflag = O_RDONLY; - - do { - fd = open(path, oflag | O_NOFOLLOW); - if (fd == -1) { - if (errno == ELOOP) - LOG_ERROR("File %s is a symlink\n", path); - - free(dir); - return PQOS_RETVAL_ERROR; - } - - oflag = O_RDONLY | O_DIRECTORY; - path = dirname(path); - - if (fd != -1) - close(fd); - } while ((strcmp(path, ".") != 0) && (strcmp(path, "/") != 0)); + FILE *stream = NULL; + struct stat lstat_val; + struct stat fstat_val; + + stream = fopen(name, mode); + if (stream == NULL) + return stream; + + fd = fileno(stream); + if (fd == -1) + goto pqos_fopen_error; + + /* collect any link info about the file */ + if (lstat(name, &lstat_val) == -1) + goto pqos_fopen_error; + + /* collect info about the opened file */ + if (fstat(fd, &fstat_val) == -1) + goto pqos_fopen_error; + + /* we should not have followed a symbolic link */ + if (lstat_val.st_mode != fstat_val.st_mode || + lstat_val.st_ino != fstat_val.st_ino || + lstat_val.st_dev != fstat_val.st_dev) { + LOG_ERROR("File %s is a symlink\n", name); + goto pqos_fopen_error; + } + + return stream; + +pqos_fopen_error: + if (stream != NULL) + fclose(stream); - free(dir); - return PQOS_RETVAL_OK; + return NULL; } -FILE * -fopen_check_symlink(const char *name, const char *mode) +char * +pqos_strcat(char *dst, const char *src, size_t size) { - int ret; - - ret = check_symlink(name); - if (ret != PQOS_RETVAL_OK) - return NULL; - - return fopen(name, mode); + return strncat(dst, src, size - strnlen(dst, size)); } diff -Nru intel-cmt-cat-3.2/lib/common.h intel-cmt-cat-4.0/lib/common.h --- intel-cmt-cat-3.2/lib/common.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/common.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,8 +56,20 @@ * @retval A valid pointer to a file or NULL on error (e.g. when the path * contains any symbolic links). */ -FILE * -fopen_check_symlink(const char *name, const char *mode); +/* clang-format off */ +FILE * pqos_fopen(const char *name, const char *mode); +/* clang-format on */ + +/** + * @brief Wrapper around strcat + * + * @param [out] dst Output buffer + * @param [in] src Input buffer + * @param [in] size Output buffer size + * + * @return output buffer + */ +char *pqos_strcat(char *dst, const char *src, size_t size); #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/lib/cpuinfo.c intel-cmt-cat-4.0/lib/cpuinfo.c --- intel-cmt-cat-3.2/lib/cpuinfo.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/cpuinfo.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,19 +40,25 @@ #include #include #include -#include /* sysconf() */ +#include /* sysconf() */ #ifdef __FreeBSD__ -#include /* sched affinity */ -#include /* sched affinity */ +#include /* sched affinity */ +#include /* sched affinity */ #endif #ifdef __linux__ -#include /* sched affinity */ +#include /* sched affinity */ #endif +#include "pqos.h" + +#include "cpu_registers.h" #include "log.h" #include "cpuinfo.h" #include "types.h" #include "machine.h" +#include "os_allocation.h" +#include "allocation.h" +#include "cap.h" /** * This structure will be made externally available @@ -61,6 +67,11 @@ static struct pqos_cpuinfo *m_cpu = NULL; /** + * intel/amd vendor configuration + */ +static struct cpuinfo_config m_config; + +/** * L2 and L3 cache info structures */ static struct pqos_cacheinfo m_l2; @@ -169,7 +180,7 @@ int thread_reported = 0; unsigned subleaf = 0; - for (subleaf = 0; ; subleaf++) { + for (subleaf = 0;; subleaf++) { struct cpuid_out leafB; unsigned level_type, level_shift; uint32_t mask; @@ -178,8 +189,8 @@ if (leafB.ebx == 0) /* invalid sub-leaf */ break; - level_type = (leafB.ecx >> 8) & 0xff; /* ECX bits 15:8 */ - level_shift = leafB.eax & 0x1f; /* EAX bits 4:0 */ + level_type = (leafB.ecx >> 8) & 0xff; /* ECX bits 15:8 */ + level_shift = leafB.eax & 0x1f; /* EAX bits 4:0 */ mask = ~(UINT32_MAX << level_shift); if (level_type == 1) { @@ -228,7 +239,7 @@ { unsigned r, p; - if (n < 2) + if (n < 2) return n; for (r = 1, p = 0; r != 0; r <<= 1, p++) @@ -265,19 +276,19 @@ memset(&m_l2, 0, sizeof(m_l2)); memset(&m_l3, 0, sizeof(m_l3)); - for (subleaf = 0; ; subleaf++) { + for (subleaf = 0;; subleaf++) { struct cpuid_out cache_info; struct pqos_cacheinfo ci; unsigned cache_type, cache_level, id, shift; lcpuid(cpuid_cache, subleaf, &cache_info); - cache_type = cache_info.eax & 0x1f; /* EAX bits 04:00 */ + cache_type = cache_info.eax & 0x1f; /* EAX bits 04:00 */ cache_level = (cache_info.eax >> 5) & 0x7; /* EAX bits 07:05 */ id = (cache_info.eax >> 14) & 0xfff; /* EAX bits 25:14 */ shift = nearest_pow2(id + 1); if (cache_type == 0 || cache_type >= 4) - break; /* no more caches or reserved */ + break; /* no more caches or reserved */ if (cache_level < DIM(cache_level_shift)) cache_level_shift[cache_level] = shift; @@ -298,8 +309,8 @@ LOG_DEBUG("CACHE: %sinclusive, %s, %s%u way(s), " "%u set(s), line size %u, %u partition(s)\n", (cache_info.edx & 2) ? "" : "not ", - (cache_info.edx & 4) ? "complex cache indexing" : - "direct mapped", + (cache_info.edx & 4) ? "complex cache indexing" + : "direct mapped", (cache_info.eax & 0x200) ? "fully associative, " : "", ci.num_ways, ci.num_sets, ci.line_size, ci.num_partitions); @@ -345,7 +356,7 @@ if (detect_apic_core_masks(apic) != 0) return -2; - if (detect_apic_cache_masks(apic, CPUID_LEAF_CACHE) != 0) + if (detect_apic_cache_masks(apic, m_config.cpuid_cache_leaf) != 0) return -3; return 0; @@ -372,7 +383,8 @@ static int detect_cpu(const int cpu, const struct apic_info *apic, - struct pqos_coreinfo *info) + struct pqos_coreinfo *info, + enum pqos_vendor vendor) { struct cpuid_out leafB; uint32_t apicid; @@ -381,27 +393,31 @@ return -1; lcpuid(0xb, 0, &leafB); - apicid = leafB.edx; /* x2APIC ID */ + apicid = leafB.edx; /* x2APIC ID */ info->lcore = cpu; info->socket = (apicid & apic->pkg_mask) >> apic->pkg_shift; info->l3_id = apicid >> apic->l3_shift; info->l2_id = apicid >> apic->l2_shift; - /* - * Update l3cat_id and mba_id. For Intel, CAT and MBA ids are - * initialized to socket id. AMD uses l3_id for both CAT and MBA - * ids. Right now, both these ids are same. This could change in - * the future. - */ - - info->l3cat_id = info->socket; - info->mba_id = info->socket; + /* + * Update l3cat_id and mba_id. For Intel, CAT and MBA ids are + * initialized to socket id. AMD uses l3_id for both CAT and MBA + * ids. Right now, both these ids are same. This could change in + * the future. + */ + + if (vendor == PQOS_VENDOR_AMD) { + info->l3cat_id = info->l3_id; + info->mba_id = info->l3_id; + } else { + info->l3cat_id = info->socket; + info->mba_id = info->socket; + } LOG_DEBUG("Detected core %u, socket %u, " "L2 ID %u, L3 ID %u, APICID %u\n", - info->lcore, info->socket, - info->l2_id, info->l3_id, apicid); + info->lcore, info->socket, info->l2_id, info->l3_id, apicid); return 0; } @@ -422,7 +438,7 @@ * @retval NULL on error */ static struct pqos_cpuinfo * -cpuinfo_build_topo(void) +cpuinfo_build_topo(enum pqos_vendor vendor) { unsigned i, max_core_count, core_count = 0; struct pqos_cpuinfo *l_cpu = NULL; @@ -445,19 +461,20 @@ return NULL; } - const size_t mem_sz = sizeof(*l_cpu) + - (max_core_count * sizeof(struct pqos_coreinfo)); + const size_t mem_sz = + sizeof(*l_cpu) + (max_core_count * sizeof(struct pqos_coreinfo)); l_cpu = (struct pqos_cpuinfo *)malloc(mem_sz); if (l_cpu == NULL) { LOG_ERROR("Couldn't allocate CPU topology structure!"); return NULL; } - l_cpu->mem_size = (unsigned) mem_sz; + l_cpu->mem_size = (unsigned)mem_sz; memset(l_cpu, 0, mem_sz); for (i = 0; i < max_core_count; i++) - if (detect_cpu(i, &apic, &l_cpu->cores[core_count]) == 0) + if (detect_cpu(i, &apic, &l_cpu->cores[core_count], vendor) == + 0) core_count++; if (set_affinity_mask(¤t_mask) != 0) { @@ -468,6 +485,7 @@ l_cpu->l2 = m_l2; l_cpu->l3 = m_l3; + l_cpu->vendor = vendor; l_cpu->num_cores = core_count; if (core_count == 0) { free(l_cpu); @@ -478,24 +496,97 @@ } /** + * @brief Detects and returns the CPU vendor + * + * Sets the vendor identification. See pqos_vendor definitions. + * + * @return detected vendor + */ +static enum pqos_vendor +detect_vendor(void) +{ + enum pqos_vendor cpu_vendor; + struct cpuid_out vendor; + + lcpuid(0x0, 0x0, &vendor); + if (vendor.ebx == 0x756e6547 && vendor.edx == 0x49656e69 && + vendor.ecx == 0x6c65746e) { + cpu_vendor = PQOS_VENDOR_INTEL; + } else if (vendor.ebx == 0x68747541 && vendor.edx == 0x69746E65 && + vendor.ecx == 0x444D4163) { + cpu_vendor = PQOS_VENDOR_AMD; + } else { + cpu_vendor = PQOS_VENDOR_UNKNOWN; + } + return cpu_vendor; +} + +/** + * Initialize pointers for the vendors + * + * @param config configuration structures + * @param vendor identification + * + * @return Operation status + * @retval Success returns 0 + */ +static int +init_config(struct cpuinfo_config *config, enum pqos_vendor vendor) +{ + memset(config, 0, sizeof(struct cpuinfo_config)); + + /** + * Make sure to initialize all the pointers to avoid + * NULL check while calling + */ + if (vendor == PQOS_VENDOR_INTEL) { + config->cpuid_cache_leaf = 4; + config->mba_max = PQOS_MBA_LINEAR_MAX; + config->mba_msr_reg = PQOS_MSR_MBA_MASK_START; + config->mba_default_val = 0; + } else if (vendor == PQOS_VENDOR_AMD) { + config->cpuid_cache_leaf = 0x8000001D; + config->mba_max = PQOS_MBA_MAX_AMD; + config->mba_msr_reg = PQOS_MSR_MBA_MASK_START_AMD; + config->mba_default_val = PQOS_MBA_MAX_AMD; + } else { + LOG_ERROR("init_config: init failed!"); + return -EFAULT; + } + + return 0; +} + +/** * Detect number of logical processors on the machine * and their location. */ int cpuinfo_init(const struct pqos_cpuinfo **topology) { + int ret; + enum pqos_vendor vendor; + if (topology == NULL) return -EINVAL; if (m_cpu != NULL) return -EPERM; - m_cpu = cpuinfo_build_topo(); + vendor = detect_vendor(); + + ret = init_config(&m_config, vendor); + if (ret != 0) + return ret; + + m_cpu = cpuinfo_build_topo(vendor); if (m_cpu == NULL) { LOG_ERROR("CPU topology detection error!"); return -EFAULT; } + m_cpu->vendor = vendor; + *topology = m_cpu; return 0; } @@ -509,3 +600,11 @@ m_cpu = NULL; return 0; } + +void +cpuinfo_get_config(const struct cpuinfo_config **config) +{ + ASSERT(config != NULL); + + *config = &m_config; +} diff -Nru intel-cmt-cat-3.2/lib/cpuinfo.h intel-cmt-cat-4.0/lib/cpuinfo.h --- intel-cmt-cat-3.2/lib/cpuinfo.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/cpuinfo.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,16 @@ #endif /** + * CPU vendor configuration value + */ +struct cpuinfo_config { + int cpuid_cache_leaf; /**< Cache mask leaf */ + unsigned mba_max; /**< default memory bandwidth */ + unsigned mba_default_val; /**< Memory bandwidth reset value */ + uint32_t mba_msr_reg; /**< MBA mask base register */ +}; + +/** * @brief Initializes CPU information module * * CPU topology detection method is OS dependent. @@ -70,6 +80,13 @@ */ int cpuinfo_fini(void); +/** + * @brief Internal API to retrieve PQoS vendor specific data + * + * @param [out] config location to store PQoS vendor specific information at + */ +void cpuinfo_get_config(const struct cpuinfo_config **config); + #ifdef __cplusplus } #endif diff -Nru intel-cmt-cat-3.2/lib/cpu_registers.h intel-cmt-cat-4.0/lib/cpu_registers.h --- intel-cmt-cat-3.2/lib/cpu_registers.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/cpu_registers.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,32 +59,43 @@ */ #define PQOS_MSR_L3CA_MASK_START 0xC90 #define PQOS_MSR_L3CA_MASK_END 0xD0F -#define PQOS_MSR_L3CA_MASK_NUMOF \ - (PQOS_MSR_L3CA_MASK_END - PQOS_MSR_L3CA_MASK_START + 1) +#define PQOS_MSR_L3CA_MASK_NUMOF \ + (PQOS_MSR_L3CA_MASK_END - PQOS_MSR_L3CA_MASK_START + 1) #define PQOS_MSR_L2CA_MASK_START 0xD10 #define PQOS_MSR_MBA_MASK_START 0xD50 -#define PQOS_MSR_L3_QOS_CFG 0xC81 /**< L3 CAT config register */ -#define PQOS_MSR_L3_QOS_CFG_CDP_EN 1ULL /**< L3 CDP enable bit */ +/** + * MBA Allocation class of service (COS) MSR register for AMD + */ +#define PQOS_MSR_MBA_MASK_START_AMD 0xC0000200 + +#define PQOS_MSR_L3_QOS_CFG 0xC81 /**< L3 CAT config register */ +#define PQOS_MSR_L3_QOS_CFG_CDP_EN 1ULL /**< L3 CDP enable bit */ -#define PQOS_MSR_L2_QOS_CFG 0xC82 /**< L2 CAT config register */ -#define PQOS_MSR_L2_QOS_CFG_CDP_EN 1ULL /**< L2 CDP enable bit */ +#define PQOS_MSR_L2_QOS_CFG 0xC82 /**< L2 CAT config register */ +#define PQOS_MSR_L2_QOS_CFG_CDP_EN 1ULL /**< L2 CDP enable bit */ +#define PQOS_MSR_MBA_CFG 0xC84 /**< MBA config register */ /** * MBA linear max value */ #define PQOS_MBA_LINEAR_MAX 100 /** + * MBA max value for AMD + */ +#define PQOS_MBA_MAX_AMD 0x800 + +/** * Available types of allocation resource ID's. * (matches CPUID enumeration) */ -#define PQOS_RES_ID_L3_ALLOCATION 1 /**< L3 cache allocation */ -#define PQOS_RES_ID_L2_ALLOCATION 2 /**< L2 cache allocation */ -#define PQOS_RES_ID_MB_ALLOCATION 3 /**< Memory BW allocation */ +#define PQOS_RES_ID_L3_ALLOCATION 1 /**< L3 cache allocation */ +#define PQOS_RES_ID_L2_ALLOCATION 2 /**< L2 cache allocation */ +#define PQOS_RES_ID_MB_ALLOCATION 3 /**< Memory BW allocation */ -#define PQOS_CPUID_CAT_CDP_BIT 2 /**< CDP supported bit */ +#define PQOS_CPUID_CAT_CDP_BIT 2 /**< CDP supported bit */ /** * Monitoring data read MSR register @@ -112,15 +123,15 @@ * These MSR's are needed to calculate IPC (instructions per clock) and * LLC miss ratio. */ -#define IA32_MSR_INST_RETIRED_ANY 0x309 -#define IA32_MSR_CPU_UNHALTED_THREAD 0x30A -#define IA32_MSR_FIXED_CTR_CTRL 0x38D -#define IA32_MSR_PERF_GLOBAL_CTRL 0x38F -#define IA32_MSR_PMC0 0x0C1 -#define IA32_MSR_PERFEVTSEL0 0x186 +#define IA32_MSR_INST_RETIRED_ANY 0x309 +#define IA32_MSR_CPU_UNHALTED_THREAD 0x30A +#define IA32_MSR_FIXED_CTR_CTRL 0x38D +#define IA32_MSR_PERF_GLOBAL_CTRL 0x38F +#define IA32_MSR_PMC0 0x0C1 +#define IA32_MSR_PERFEVTSEL0 0x186 -#define IA32_EVENT_LLC_MISS_MASK 0x2EULL -#define IA32_EVENT_LLC_MISS_UMASK 0x41ULL +#define IA32_EVENT_LLC_MISS_MASK 0x2EULL +#define IA32_EVENT_LLC_MISS_UMASK 0x41ULL #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/lib/hw_cap.c intel-cmt-cat-4.0/lib/hw_cap.c --- intel-cmt-cat-3.2/lib/hw_cap.c 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/lib/hw_cap.c 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,872 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @brief HW implementation of PQoS API / capabilities. + */ +#include +#include + +#include "cpu_registers.h" +#include "hw_cap.h" +#include "log.h" +#include "machine.h" +#include "types.h" + +/** + * @brief Retrieves cache size and number of ways + * + * Retrieves information about cache from \a cache_info structure. + * + * @param cache_info cache information structure + * @param num_ways place to store number of cache ways + * @param size place to store cache size in bytes + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_PARAM incorrect parameters + * @retval PQOS_RETVAL_RESOURCE cache not detected + */ +static int +get_cache_info(const struct pqos_cacheinfo *cache_info, + unsigned *num_ways, + unsigned *size) +{ + if (num_ways == NULL && size == NULL) + return PQOS_RETVAL_PARAM; + if (cache_info == NULL) + return PQOS_RETVAL_PARAM; + if (!cache_info->detected) + return PQOS_RETVAL_RESOURCE; + if (num_ways != NULL) + *num_ways = cache_info->num_ways; + if (size != NULL) + *size = cache_info->total_size; + return PQOS_RETVAL_OK; +} + +/** + * @brief Adds new event type to \a mon monitoring structure + * + * @param mon Monitoring structure which is to be updated with the new + * event type + * @param res_id resource id + * @param event_type event type + * @param max_rmid max RMID for the event + * @param scale_factor event specific scale factor + * @param counter_length counter bit length for the event + * @param max_num_events maximum number of events that \a mon can accommodate + */ +static void +add_monitoring_event(struct pqos_cap_mon *mon, + const unsigned res_id, + const int event_type, + const unsigned max_rmid, + const uint32_t scale_factor, + const unsigned counter_length, + const unsigned max_num_events) +{ + if (mon->num_events >= max_num_events) { + LOG_WARN("%s() no space for event type %d (resource id %u)!\n", + __func__, event_type, res_id); + return; + } + + LOG_DEBUG("Adding monitoring event: resource ID %u, " + "type %d to table index %u\n", + res_id, event_type, mon->num_events); + + mon->events[mon->num_events].type = (enum pqos_mon_event)event_type; + mon->events[mon->num_events].max_rmid = max_rmid; + mon->events[mon->num_events].scale_factor = scale_factor; + mon->events[mon->num_events].counter_length = counter_length; + mon->num_events++; +} + +/** + * @brief Discovers monitoring capabilities + * + * Runs series of CPUID instructions to discover system CMT + * capabilities. + * Allocates memory for monitoring structure and + * returns it through \a r_mon to the caller. + * + * @param r_mon place to store created monitoring structure + * @param cpu CPU topology structure + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_RESOURCE monitoring not supported + * @retval PQOS_RETVAL_ERROR enumeration error + */ +int +hw_cap_mon_discover(struct pqos_cap_mon **r_mon, const struct pqos_cpuinfo *cpu) +{ + struct cpuid_out res, cpuid_0xa; + struct cpuid_out cpuid_0xf_1; + int ret = PQOS_RETVAL_OK; + unsigned sz = 0, max_rmid = 0, l3_size = 0, num_events = 0; + struct pqos_cap_mon *mon = NULL; + + ASSERT(r_mon != NULL && cpu != NULL); + + /** + * Run CPUID.0x7.0 to check + * for quality monitoring capability (bit 12 of ebx) + */ + lcpuid(0x7, 0x0, &res); + if (!(res.ebx & (1 << 12))) { + LOG_WARN("CPUID.0x7.0: Monitoring capability not supported!\n"); + return PQOS_RETVAL_RESOURCE; + } + + /** + * We can go to CPUID.0xf.0 for further + * exploration of monitoring capabilities + */ + lcpuid(0xf, 0x0, &res); + if (!(res.edx & (1 << 1))) { + LOG_WARN("CPUID.0xf.0: Monitoring capability not supported!\n"); + return PQOS_RETVAL_RESOURCE; + } + + /** + * MAX_RMID for the socket + */ + max_rmid = (unsigned)res.ebx + 1; + ret = get_cache_info(&cpu->l3, NULL, &l3_size); /**< L3 cache size */ + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("Error reading L3 information!\n"); + return PQOS_RETVAL_ERROR; + } + + /** + * Check number of monitoring events to allocate memory for + * Sub-leaf 1 provides information on monitoring. + */ + lcpuid(0xf, 1, &cpuid_0xf_1); /**< query resource monitoring */ + + if (cpuid_0xf_1.edx & 1) + num_events++; /**< LLC occupancy */ + if (cpuid_0xf_1.edx & 2) + num_events++; /**< total memory bandwidth event */ + if (cpuid_0xf_1.edx & 4) + num_events++; /**< local memory bandwidth event */ + if ((cpuid_0xf_1.edx & 2) && (cpuid_0xf_1.edx & 4)) + num_events++; /**< remote memory bandwidth virtual event */ + + if (!num_events) + return PQOS_RETVAL_ERROR; + + /** + * Check if IPC can be calculated & supported + */ + lcpuid(0xa, 0x0, &cpuid_0xa); + if (((cpuid_0xa.ebx & 3) == 0) && ((cpuid_0xa.edx & 31) > 1)) + num_events++; + + /** + * This means we can program LLC misses too + */ + if (((cpuid_0xa.eax >> 8) & 0xff) > 1) + num_events++; + + /** + * Allocate memory for detected events and + * fill the events in. + */ + sz = (num_events * sizeof(struct pqos_monitor)) + sizeof(*mon); + mon = (struct pqos_cap_mon *)malloc(sz); + if (mon == NULL) + return PQOS_RETVAL_RESOURCE; + + memset(mon, 0, sz); + mon->mem_size = sz; + mon->max_rmid = max_rmid; + mon->l3_size = l3_size; + + { + const unsigned max_rmid = cpuid_0xf_1.ecx + 1; + const uint32_t scale_factor = cpuid_0xf_1.ebx; + const unsigned counter_length = (cpuid_0xf_1.eax & 0x7f) + 24; + + if (cpuid_0xf_1.edx & 1) + add_monitoring_event(mon, 1, PQOS_MON_EVENT_L3_OCCUP, + max_rmid, scale_factor, + counter_length, num_events); + if (cpuid_0xf_1.edx & 2) + add_monitoring_event(mon, 1, PQOS_MON_EVENT_TMEM_BW, + max_rmid, scale_factor, + counter_length, num_events); + if (cpuid_0xf_1.edx & 4) + add_monitoring_event(mon, 1, PQOS_MON_EVENT_LMEM_BW, + max_rmid, scale_factor, + counter_length, num_events); + + if ((cpuid_0xf_1.edx & 2) && (cpuid_0xf_1.edx & 4)) + add_monitoring_event(mon, 1, PQOS_MON_EVENT_RMEM_BW, + max_rmid, scale_factor, + counter_length, num_events); + } + + if (((cpuid_0xa.ebx & 3) == 0) && ((cpuid_0xa.edx & 31) > 1)) + add_monitoring_event(mon, 0, PQOS_PERF_EVENT_IPC, 0, 0, 0, + num_events); + + if (((cpuid_0xa.eax >> 8) & 0xff) > 1) + add_monitoring_event(mon, 0, PQOS_PERF_EVENT_LLC_MISS, 0, 0, 0, + num_events); + + (*r_mon) = mon; + return PQOS_RETVAL_OK; +} + +/** + * @brief Checks L3 CDP enable status across all CPU sockets + * + * It also validates if L3 CDP enabling is consistent across + * CPU sockets. + * At the moment, such scenario is considered as error + * that requires CAT reset. + * + * @param cpu detected CPU topology + * @param enabled place to store L3 CDP enabling status + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +static int +l3cdp_is_enabled(const struct pqos_cpuinfo *cpu, int *enabled) +{ + unsigned *l3cat_ids = NULL; + unsigned l3cat_id_num = 0, j = 0; + unsigned enabled_num = 0, disabled_num = 0; + int ret = PQOS_RETVAL_OK; + + ASSERT(enabled != NULL && cpu != NULL); + if (enabled == NULL || cpu == NULL) + return PQOS_RETVAL_PARAM; + + *enabled = 0; + + /** + * Get list of l3cat id's + */ + l3cat_ids = pqos_cpu_get_l3cat_ids(cpu, &l3cat_id_num); + if (l3cat_ids == NULL) + return PQOS_RETVAL_RESOURCE; + + for (j = 0; j < l3cat_id_num; j++) { + uint64_t reg = 0; + unsigned core = 0; + + ret = pqos_cpu_get_one_by_l3cat_id(cpu, l3cat_ids[j], &core); + if (ret != PQOS_RETVAL_OK) + goto l3cdp_is_enabled_exit; + + if (msr_read(core, PQOS_MSR_L3_QOS_CFG, ®) != + MACHINE_RETVAL_OK) { + ret = PQOS_RETVAL_ERROR; + goto l3cdp_is_enabled_exit; + } + + if (reg & PQOS_MSR_L3_QOS_CFG_CDP_EN) + enabled_num++; + else + disabled_num++; + } + + if (disabled_num > 0 && enabled_num > 0) { + LOG_ERROR("Inconsistent L3 CDP settings across l3cat_ids." + "Please reset CAT or reboot your system!\n"); + ret = PQOS_RETVAL_ERROR; + goto l3cdp_is_enabled_exit; + } + + if (enabled_num > 0) + *enabled = 1; + + LOG_INFO("L3 CDP is %s\n", (*enabled) ? "enabled" : "disabled"); + +l3cdp_is_enabled_exit: + if (l3cat_ids != NULL) + free(l3cat_ids); + + return ret; +} + +/** + * @brief Detects presence of L3 CAT based on register probing. + * + * This method of detecting CAT does the following steps. + * - probe COS registers one by one and exit on first error + * - if procedure fails on COS0 then CAT is not supported + * - use CPUID.0x4.0x3 to get number of cache ways + * + * @param cap CAT structure to be initialized + * @param cpu CPU topology structure + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_PARAM invalid input configuration/parameters + * @retval PQOS_RETVAL_RESOURCE technology not supported + */ +static int +hw_cap_l3ca_probe(struct pqos_cap_l3ca *cap, const struct pqos_cpuinfo *cpu) +{ + unsigned i = 0, lcore; + const unsigned max_classes = + PQOS_MSR_L3CA_MASK_END - PQOS_MSR_L3CA_MASK_START + 1; + + ASSERT(cap != NULL && cpu != NULL); + + /** + * Pick a valid core and run series of MSR reads on it + */ + lcore = cpu->cores[0].lcore; + for (i = 0; i < max_classes; i++) { + int msr_ret; + uint64_t value; + + msr_ret = msr_read(lcore, PQOS_MSR_L3CA_MASK_START + i, &value); + if (msr_ret != MACHINE_RETVAL_OK) + break; + } + + if (i == 0) { + LOG_WARN("Error probing COS0 on core %u\n", lcore); + return PQOS_RETVAL_RESOURCE; + } + + /** + * Number of ways and CBM is detected with CPUID.0x4.0x3 later on + */ + cap->num_classes = i; + return PQOS_RETVAL_OK; +} + +/** + * @brief Detects presence of L3 CAT based on brand string. + * + * If CPUID.0x7.0 doesn't report CAT feature + * platform may still support it: + * - we need to check brand string vs known ones + * - use CPUID.0x4.0x3 to get number of cache ways + * + * @param cap CAT structure to be initialized + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_RESOURCE technology not supported + */ +static int +hw_cap_l3ca_brandstr(struct pqos_cap_l3ca *cap) +{ +#define CPUID_LEAF_BRAND_START 0x80000002UL +#define CPUID_LEAF_BRAND_END 0x80000004UL + +#define CPUID_LEAF_BRAND_NUM (CPUID_LEAF_BRAND_END - CPUID_LEAF_BRAND_START + 1) +#define MAX_BRAND_STRING_LEN (CPUID_LEAF_BRAND_NUM * 4 * sizeof(uint32_t)) + static const char *const supported_brands[] = { + "E5-2658 v3", "E5-2648L v3", "E5-2628L v3", "E5-2618L v3", + "E5-2608L v3", "E5-2658A v3", "E3-1258L v4", "E3-1278L v4"}; + struct cpuid_out res; + int ret = PQOS_RETVAL_OK; + int match_found = 0; + uint32_t brand[MAX_BRAND_STRING_LEN / 4 + 1]; + char *brand_str = (char *)brand; + uint32_t *brand_u32 = brand; + unsigned i = 0; + + /** + * Assume \a cap is not NULL at this stage. + * Adequate check has to be done in the caller. + */ + ASSERT(cap != NULL); + + lcpuid(0x80000000, 0, &res); + if (res.eax < CPUID_LEAF_BRAND_END) { + LOG_ERROR("Brand string CPU-ID extended functions " + "not supported\n"); + return PQOS_RETVAL_ERROR; + } + + memset(brand, 0, sizeof(brand)); + + for (i = 0; i < CPUID_LEAF_BRAND_NUM; i++) { + lcpuid((unsigned)CPUID_LEAF_BRAND_START + i, 0, &res); + *brand_u32++ = res.eax; + *brand_u32++ = res.ebx; + *brand_u32++ = res.ecx; + *brand_u32++ = res.edx; + } + + LOG_DEBUG("CPU brand string '%s'\n", brand_str); + + /** + * match brand against supported ones + */ + for (i = 0; i < DIM(supported_brands); i++) + if (strstr(brand_str, supported_brands[i]) != NULL) { + LOG_INFO("Cache allocation detected for model name " + "'%s'\n", + brand_str); + match_found = 1; + break; + } + + if (!match_found) { + LOG_WARN("Cache allocation not supported on model name '%s'!\n", + brand_str); + return PQOS_RETVAL_RESOURCE; + } + + /** + * Figure out number of ways and CBM (1:1) + * using CPUID.0x4.0x3 + */ + cap->num_classes = 4; + + return ret; +} + +/** + * @brief Detects presence of L3 CAT based on CPUID + * + * @param cap CAT structure to be initialized + * @param cpu CPU topology structure + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_RESOURCE technology not supported + */ +static int +hw_cap_l3ca_cpuid(struct pqos_cap_l3ca *cap, const struct pqos_cpuinfo *cpu) +{ + struct cpuid_out res; + int ret = PQOS_RETVAL_OK; + + /** + * We can go to CPUID.0x10.0 to explore + * allocation capabilities + */ + lcpuid(0x10, 0x0, &res); + if (!(res.ebx & (1 << PQOS_RES_ID_L3_ALLOCATION))) { + LOG_INFO("CPUID.0x10.0: L3 CAT not detected.\n"); + return PQOS_RETVAL_RESOURCE; + } + + /** + * L3 CAT detected + * - get more info about it + */ + lcpuid(0x10, PQOS_RES_ID_L3_ALLOCATION, &res); + + cap->num_classes = res.edx + 1; + cap->num_ways = res.eax + 1; + cap->cdp = (res.ecx >> PQOS_CPUID_CAT_CDP_BIT) & 1; + cap->cdp_on = 0; + cap->way_contention = (uint64_t)res.ebx; + + if (cap->cdp) { + /** + * CDP is supported but is it on? + */ + int cdp_on = 0; + + ret = l3cdp_is_enabled(cpu, &cdp_on); + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("L3 CDP detection error!\n"); + return ret; + } + cap->cdp_on = cdp_on; + if (cdp_on) + cap->num_classes = cap->num_classes / 2; + } + + return ret; +} + +/** + * @brief Discovers L3 CAT + * + * First it tries to detects CAT through CPUID.0x7.0 + * if this fails then falls into brand string check. + * + * Function allocates memory for CAT capabilities + * and returns it to the caller through \a r_cap. + * + * \a cpu is only needed to detect CDP status. + * + * @param cap place to store CAT capabilities structure + * @param cpu detected cpu topology + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + */ +int +hw_cap_l3ca_discover(struct pqos_cap_l3ca *cap, const struct pqos_cpuinfo *cpu) +{ + struct cpuid_out res; + unsigned l3_size = 0; + int ret = PQOS_RETVAL_OK; + + ASSERT(cap != NULL); + ASSERT(cpu != NULL); + + memset(cap, 0, sizeof(*cap)); + cap->mem_size = sizeof(*cap); + + /** + * Run CPUID.0x7.0 to check + * for allocation capability (bit 15 of ebx) + */ + lcpuid(0x7, 0x0, &res); + + if (res.ebx & (1 << 15)) { + /** + * Use CPUID method + */ + LOG_INFO("CPUID.0x7.0: L3 CAT supported\n"); + ret = hw_cap_l3ca_cpuid(cap, cpu); + if (ret == PQOS_RETVAL_OK) + ret = get_cache_info(&cpu->l3, NULL, &l3_size); + } else { + /** + * Use brand string matching method 1st. + * If it fails then try register probing. + */ + LOG_INFO("CPUID.0x7.0: L3 CAT not detected. " + "Checking brand string...\n"); + ret = hw_cap_l3ca_brandstr(cap); + if (ret != PQOS_RETVAL_OK) + ret = hw_cap_l3ca_probe(cap, cpu); + if (ret == PQOS_RETVAL_OK) + ret = + get_cache_info(&cpu->l3, &cap->num_ways, &l3_size); + } + + if (cap->num_ways > 0) + cap->way_size = l3_size / cap->num_ways; + + return ret; +} + +/** + * @brief Checks L2 CDP enable status across all CPU clusters + * + * It also validates if L2 CDP enabling is consistent across + * CPU clusters. + * At the moment, such scenario is considered as error + * that requires CAT reset. + * + * @param cpu detected CPU topology + * @param enabled place to store L2 CDP enabling status + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +static int +l2cdp_is_enabled(const struct pqos_cpuinfo *cpu, int *enabled) +{ + unsigned *l2ids = NULL; + unsigned l2id_num = 0; + unsigned enabled_num = 0, disabled_num = 0; + unsigned i; + int ret = PQOS_RETVAL_OK; + + /** + * Get list of L2 clusters id's + */ + l2ids = pqos_cpu_get_l2ids(cpu, &l2id_num); + if (l2ids == NULL || l2id_num == 0) { + ret = PQOS_RETVAL_RESOURCE; + goto l2cdp_is_enabled_exit; + } + + for (i = 0; i < l2id_num; i++) { + uint64_t reg = 0; + unsigned core = 0; + + ret = pqos_cpu_get_one_by_l2id(cpu, l2ids[i], &core); + if (ret != PQOS_RETVAL_OK) + goto l2cdp_is_enabled_exit; + + if (msr_read(core, PQOS_MSR_L2_QOS_CFG, ®) != + MACHINE_RETVAL_OK) { + ret = PQOS_RETVAL_ERROR; + goto l2cdp_is_enabled_exit; + } + + if (reg & PQOS_MSR_L2_QOS_CFG_CDP_EN) + enabled_num++; + else + disabled_num++; + } + + if (disabled_num > 0 && enabled_num > 0) { + LOG_ERROR("Inconsistent L2 CDP settings across clusters." + "Please reset CAT or reboot your system!\n"); + ret = PQOS_RETVAL_ERROR; + goto l2cdp_is_enabled_exit; + } + + if (enabled_num > 0) + *enabled = 1; + + LOG_INFO("L2 CDP is %s\n", (*enabled) ? "enabled" : "disabled"); + +l2cdp_is_enabled_exit: + if (l2ids != NULL) + free(l2ids); + + return ret; +} + +int +hw_cap_l2ca_discover(struct pqos_cap_l2ca *cap, const struct pqos_cpuinfo *cpu) +{ + struct cpuid_out res; + unsigned l2_size = 0; + int ret = PQOS_RETVAL_OK; + + ASSERT(cpu != NULL); + ASSERT(cap != NULL); + + /** + * Run CPUID.0x7.0 to check + * for allocation capability (bit 15 of ebx) + */ + lcpuid(0x7, 0x0, &res); + if (!(res.ebx & (1 << 15))) { + LOG_INFO("CPUID.0x7.0: L2 CAT not supported\n"); + return PQOS_RETVAL_RESOURCE; + } + + /** + * We can go to CPUID.0x10.0 to obtain more info + */ + lcpuid(0x10, 0x0, &res); + if (!(res.ebx & (1 << PQOS_RES_ID_L2_ALLOCATION))) { + LOG_INFO("CPUID 0x10.0: L2 CAT not supported!\n"); + return PQOS_RETVAL_RESOURCE; + } + + lcpuid(0x10, PQOS_RES_ID_L2_ALLOCATION, &res); + + memset(cap, 0, sizeof(*cap)); + cap->mem_size = sizeof(*cap); + cap->num_classes = res.edx + 1; + cap->num_ways = res.eax + 1; + cap->cdp = (res.ecx >> PQOS_CPUID_CAT_CDP_BIT) & 1; + cap->cdp_on = 0; + cap->way_contention = (uint64_t)res.ebx; + + if (cap->cdp) { + int cdp_on = 0; + + /* + * Check if L2 CDP is enabled + */ + ret = l2cdp_is_enabled(cpu, &cdp_on); + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("L2 CDP detection error!\n"); + return ret; + } + cap->cdp_on = cdp_on; + if (cdp_on) + cap->num_classes = cap->num_classes / 2; + } + + ret = get_cache_info(&cpu->l2, NULL, &l2_size); + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("Error reading L2 info!\n"); + return PQOS_RETVAL_ERROR; + } + if (cap->num_ways > 0) + cap->way_size = l2_size / cap->num_ways; + + return ret; +} + +int +hw_cap_mba_discover(struct pqos_cap_mba *cap, const struct pqos_cpuinfo *cpu) +{ + struct cpuid_out res; + int ret = PQOS_RETVAL_OK; + unsigned version; + unsigned mba_thread_ctrl = 0; + + ASSERT(cpu != NULL); + ASSERT(cap != NULL); + + memset(cap, 0, sizeof(*cap)); + cap->mem_size = sizeof(*cap); + cap->ctrl = -1; + cap->ctrl_on = 0; + + /** + * Run CPUID.0x7.0 to check + * for allocation capability (bit 15 of ebx) + */ + lcpuid(0x7, 0x0, &res); + if (!(res.ebx & (1 << 15))) { + LOG_INFO("CPUID.0x7.0: MBA not supported\n"); + return PQOS_RETVAL_RESOURCE; + } + + /** + * We can go to CPUID.0x10.0 to obtain more info + */ + lcpuid(0x10, 0x0, &res); + if (!(res.ebx & (1 << PQOS_RES_ID_MB_ALLOCATION))) { + LOG_INFO("CPUID 0x10.0: MBA not supported!\n"); + return PQOS_RETVAL_RESOURCE; + } + + lcpuid(0x10, PQOS_RES_ID_MB_ALLOCATION, &res); + + cap->num_classes = (res.edx & 0xffff) + 1; + cap->throttle_max = (res.eax & 0xfff) + 1; + cap->is_linear = (res.ecx >> 2) & 1; + if (cap->is_linear) + cap->throttle_step = 100 - cap->throttle_max; + else { + LOG_WARN("MBA non-linear mode not supported yet!\n"); + return PQOS_RETVAL_RESOURCE; + } + + /* + * Detect MBA version + * - MBA3.0 introduces per-thread MBA controls + * - MBA2.0 increases number of MBA COS to 15 + */ + if (res.ecx & 0x1) { + version = 3; + mba_thread_ctrl = 1; + } else if (cap->num_classes > 8) + version = 2; + else + version = 1; + + LOG_INFO("Detected MBA version %u.0\n", version); + LOG_INFO("Detected Per-%s MBA controls\n", + mba_thread_ctrl ? "Thread" : "Core"); + + if (version >= 2) { + unsigned *mba_ids; + unsigned mba_id_num; + unsigned i; + + /* mba ids */ + mba_ids = pqos_cpu_get_mba_ids(cpu, &mba_id_num); + if (mba_ids == NULL) + return PQOS_RETVAL_RESOURCE; + + /* Detect MBA configuration */ + for (i = 0; i < mba_id_num; i++) { + uint64_t reg = 0; + unsigned core = 0; + + ret = + pqos_cpu_get_one_by_mba_id(cpu, mba_ids[i], &core); + if (ret != PQOS_RETVAL_OK) + break; + + if (msr_read(core, PQOS_MSR_MBA_CFG, ®) != + MACHINE_RETVAL_OK) { + ret = PQOS_RETVAL_ERROR; + break; + } + + if (reg & 0x2) + LOG_INFO( + "MBA Legacy Mode enabled on socket %u\n", + mba_ids[i]); + if (!mba_thread_ctrl) + LOG_INFO("%s MBA delay enabled on socket %u\n", + (reg & 0x1) ? "Min" : "Max", + mba_ids[i]); + } + + free(mba_ids); + } + + return ret; +} + +int +amd_cap_mba_discover(struct pqos_cap_mba *cap, const struct pqos_cpuinfo *cpu) +{ + struct cpuid_out res; + int ret = PQOS_RETVAL_OK; + + UNUSED_PARAM(cpu); + ASSERT(cap != NULL); + + memset(cap, 0, sizeof(*cap)); + cap->mem_size = sizeof(*cap); + cap->ctrl = -1; + cap->ctrl_on = 0; + + /** + * Run CPUID.0x80000008.0 to check + * for MBA allocation capability (bit 6 of ebx) + */ + lcpuid(0x80000008, 0x0, &res); + if (!(res.ebx & (1 << 6))) { + LOG_INFO("CPUID.0x80000008.0: MBA not supported\n"); + free(cap); + return PQOS_RETVAL_RESOURCE; + } + + /** + * We can go to CPUID.0x10.0 to obtain more info + */ + lcpuid(0x80000020, 0x0, &res); + if (!(res.ebx & (1 << 1))) { + LOG_INFO("CPUID 0x10.0: MBA not supported!\n"); + free(cap); + return PQOS_RETVAL_RESOURCE; + } + + lcpuid(0x80000020, 1, &res); + + cap->num_classes = (res.edx & 0xffff) + 1; + + /* AMD does not support throttle_max and is_linear. Set it to 0 */ + cap->throttle_max = 0; + cap->is_linear = 0; + + return ret; +} diff -Nru intel-cmt-cat-3.2/lib/hw_cap.h intel-cmt-cat-4.0/lib/hw_cap.h --- intel-cmt-cat-3.2/lib/hw_cap.h 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/lib/hw_cap.h 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,108 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 __PQOS_HW_CAP_H__ +#define __PQOS_HW_CAP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pqos.h" + +/** + * @brief Discovers HW monitoring support + * + * @param r_cap place to store monitoring capabilities structure + * @param cpu detected cpu topology + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + */ +int hw_cap_mon_discover(struct pqos_cap_mon **r_cap, + const struct pqos_cpuinfo *cpu); + +/** + * @brief Discovers HW support of L3 CAT + * + * @param cap place to store CAT capabilities + * @param cpu detected cpu topology + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + */ +int hw_cap_l3ca_discover(struct pqos_cap_l3ca *cap, + const struct pqos_cpuinfo *cpu); + +/** + * @brief Discovers HW support of L2 CAT + * + * @param cap place to store L2 CAT capabilities + * @param cpu CPU topology structure + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + */ +int hw_cap_l2ca_discover(struct pqos_cap_l2ca *cap, + const struct pqos_cpuinfo *cpu); + +/** + * @brief Discovers HW support of MBA + * + * @param cap place to store MBA capabilities + * @param cpu detected cpu topology + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + */ +int hw_cap_mba_discover(struct pqos_cap_mba *cap, + const struct pqos_cpuinfo *cpu); + +/** + * @brief Discovers MBA support for AMD + * + * @param cap place to store MBA capabilities + * @param cpu detected cpu topology + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_RESOURCE if not supported + */ +int amd_cap_mba_discover(struct pqos_cap_mba *cap, + const struct pqos_cpuinfo *cpu); + +#ifdef __cplusplus +} +#endif + +#endif /* __PQOS_HW_CAP_H__ */ diff -Nru intel-cmt-cat-3.2/lib/hw_monitoring.c intel-cmt-cat-4.0/lib/hw_monitoring.c --- intel-cmt-cat-3.2/lib/hw_monitoring.c 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/lib/hw_monitoring.c 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,1387 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @brief Implementation of HW PQoS monitoring API. + * + * CPUID and MSR operations are done on 'local' system. + * + */ + +#include +#include + +#include "cap.h" +#include "cpu_registers.h" +#include "log.h" +#include "hw_monitoring.h" +#include "machine.h" +#include "monitoring.h" +#include "perf_monitoring.h" + +/** + * --------------------------------------- + * Local macros + * --------------------------------------- + */ + +/** + * Special RMID - after reset all cores are associated with it. + * + * The assumption is that if core is not assigned to it + * then it is subject of monitoring activity by a different process. + */ +#define RMID0 (0) + +/** + * --------------------------------------- + * Local data types + * --------------------------------------- + */ + +/** + * --------------------------------------- + * Local data structures + * --------------------------------------- + */ +static unsigned m_rmid_max = 0; /**< max RMID */ +#ifdef PQOS_RMID_CUSTOM +/* clang-format off */ +/** Custom RMID configuration */ +static struct pqos_rmid_config rmid_cfg = {PQOS_RMID_TYPE_DEFAULT, + {0, NULL, NULL} }; +/* clang-format on */ +#endif + +/** List of non-virtual perf events */ +static const enum pqos_mon_event perf_event[] = { + PQOS_PERF_EVENT_LLC_MISS, (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES, + (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS}; + +/** + * --------------------------------------- + * Local Functions + * --------------------------------------- + */ + +static int mon_assoc_set(const unsigned lcore, const pqos_rmid_t rmid); + +static int mon_assoc_get(const unsigned lcore, pqos_rmid_t *rmid); + +static int mon_read(const unsigned lcore, + const pqos_rmid_t rmid, + const enum pqos_mon_event event, + uint64_t *value); + +static unsigned get_event_id(const enum pqos_mon_event event); + +static uint64_t scale_event(const enum pqos_mon_event event, + const uint64_t val); + +/* + * ======================================= + * ======================================= + * + * initialize and shutdown + * + * ======================================= + * ======================================= + */ + +int +hw_mon_init(const struct pqos_cpuinfo *cpu, + const struct pqos_cap *cap, + const struct pqos_config *cfg) +{ + int ret; + const struct pqos_capability *item = NULL; + + UNUSED_PARAM(cpu); + + ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MON, &item); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; + + m_rmid_max = item->u.mon->max_rmid; + if (m_rmid_max == 0) { + ret = PQOS_RETVAL_PARAM; + goto hw_mon_init_exit; + } + LOG_DEBUG("Max RMID per monitoring cluster is %u\n", m_rmid_max); + +#ifdef __linux__ + ret = perf_mon_init(cpu, cap); + /* perf MBM is not supported */ + if (ret == PQOS_RETVAL_RESOURCE) + ret = PQOS_RETVAL_OK; + else if (ret != PQOS_RETVAL_OK) + goto hw_mon_init_exit; +#endif + +#ifdef PQOS_RMID_CUSTOM + rmid_cfg.type = cfg->rmid_cfg.type; + if (cfg->rmid_cfg.type == PQOS_RMID_TYPE_MAP) { + const unsigned num = cfg->rmid_cfg.map.num; + unsigned i; + + if (cfg->rmid_cfg.map.core == NULL || + cfg->rmid_cfg.map.rmid == NULL) { + ret = PQOS_RETVAL_PARAM; + goto hw_mon_init_exit; + } + + rmid_cfg.map.num = num; + rmid_cfg.map.core = (unsigned *)malloc(sizeof(unsigned) * num); + rmid_cfg.map.rmid = + (pqos_rmid_t *)malloc(sizeof(pqos_rmid_t) * num); + + for (i = 0; i < num; i++) { + rmid_cfg.map.core[i] = cfg->rmid_cfg.map.core[i]; + rmid_cfg.map.rmid[i] = cfg->rmid_cfg.map.rmid[i]; + } + } +#else + UNUSED_PARAM(cfg); +#endif + +hw_mon_init_exit: + if (ret != PQOS_RETVAL_OK) + hw_mon_fini(); + + return ret; +} + +int +hw_mon_fini(void) +{ + m_rmid_max = 0; + +#ifdef __linux__ + perf_mon_fini(); +#endif + +#ifdef PQOS_RMID_CUSTOM + if (rmid_cfg.map.core != NULL) + free(rmid_cfg.map.core); + if (rmid_cfg.map.rmid != NULL) + free(rmid_cfg.map.rmid); +#endif + + return PQOS_RETVAL_OK; +} + +/* + * ======================================= + * ======================================= + * + * RMID allocation + * + * ======================================= + * ======================================= + */ + +/** + * @brief Gets max RMID number for given \a event + * + * @param [out] rmid resource monitoring id + * @param [in] event Monitoring event type + * + * @return Operations status + */ +static int +rmid_get_event_max(pqos_rmid_t *rmid, const enum pqos_mon_event event) +{ + pqos_rmid_t max_rmid = m_rmid_max; + const struct pqos_capability *item = NULL; + const struct pqos_cap_mon *mon = NULL; + unsigned mask_found = 0; + unsigned i; + int ret; + + if (rmid == NULL) + return PQOS_RETVAL_PARAM; + + /** + * This is not so straight forward as it appears to be. + * We first have to figure out max RMID + * for given event type. In order to do so we need: + * - go through capabilities structure + * - find monitoring capability + * - look for the \a event in the event list + * - find max RMID matching the \a event + */ + ret = _pqos_cap_get_type(PQOS_CAP_TYPE_MON, &item); + if (ret != PQOS_RETVAL_OK) + return ret; + ASSERT(item != NULL); + mon = item->u.mon; + + /* Find which events are supported vs requested */ + max_rmid = m_rmid_max; + for (i = 0; i < mon->num_events; i++) + if (event & mon->events[i].type) { + mask_found |= mon->events[i].type; + max_rmid = (max_rmid > mon->events[i].max_rmid) + ? mon->events[i].max_rmid + : max_rmid; + } + + /** + * Check if all of the events are supported + */ + if (event != mask_found || max_rmid == 0) + return PQOS_RETVAL_ERROR; + + ASSERT(m_rmid_max >= max_rmid); + + *rmid = max_rmid; + return PQOS_RETVAL_OK; +} + +/** + * @brief Get used RMIDs on ctx->cluster + * + * @param [inout] ctx poll context + * @param [in] event Monitoring event type + * + * @return Operations status + */ +static int +rmid_alloc(struct pqos_mon_poll_ctx *ctx, const enum pqos_mon_event event) +{ + const struct pqos_cpuinfo *cpu; + int ret = PQOS_RETVAL_OK; + unsigned max_rmid = 0; + unsigned *core_list = NULL; + unsigned i, core_count; + pqos_rmid_t *rmid_list = NULL; + + ASSERT(ctx != NULL); + + _pqos_cap_get(NULL, &cpu); + + /* Getting max RMID for given event */ + ret = rmid_get_event_max(&max_rmid, event); + if (ret != PQOS_RETVAL_OK) + return ret; + + /** + * Check for free RMID in the cluster by reading current associations. + */ + core_list = pqos_cpu_get_cores_l3id(cpu, ctx->cluster, &core_count); + if (core_list == NULL) + return PQOS_RETVAL_ERROR; + ASSERT(core_count > 0); + rmid_list = (pqos_rmid_t *)malloc(sizeof(rmid_list[0]) * core_count); + if (rmid_list == NULL) { + ret = PQOS_RETVAL_RESOURCE; + goto rmid_alloc_error; + } + + for (i = 0; i < core_count; i++) { + ret = mon_assoc_get(core_list[i], &rmid_list[i]); + if (ret != PQOS_RETVAL_OK) + goto rmid_alloc_error; + } + + ret = PQOS_RETVAL_ERROR; + for (i = 1; i < max_rmid; i++) { + unsigned j = 0; + + for (j = 0; j < core_count; j++) + if (i == rmid_list[j]) + break; + if (j >= core_count) { + ret = PQOS_RETVAL_OK; + ctx->rmid = i; + break; + } + } + +rmid_alloc_error: + if (rmid_list != NULL) + free(rmid_list); + if (core_list != NULL) + free(core_list); + return ret; +} + +#ifdef PQOS_RMID_CUSTOM +/** + * @brief Gets RMID value based on information stored in rmid_cfg + * + * @param [inout] ctx poll context + * @param [in] event Monitoring event type + * @param [in] rmid_cfg rmid configuration parameters + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +rmid_alloc_custom(struct pqos_mon_poll_ctx *ctx, + const enum pqos_mon_event event, + const struct pqos_rmid_config *rmid_cfg) +{ + if (ctx == NULL) + return PQOS_RETVAL_PARAM; + + if (rmid_cfg == NULL || rmid_cfg->type == PQOS_RMID_TYPE_DEFAULT) { + return rmid_alloc(ctx, event); + } else if (rmid_cfg->type == PQOS_RMID_TYPE_MAP) { + unsigned i; + + for (i = 0; i < rmid_cfg->map.num; i++) { + if (ctx->lcore == rmid_cfg->map.core[i]) { + ctx->rmid = rmid_cfg->map.rmid[i]; + return PQOS_RETVAL_OK; + } + } + + LOG_ERROR("RMID Custom: No mapping for core %u\n", ctx->lcore); + } else { + LOG_ERROR("RMID Custom: Unsupported rmid type: %u\n", + rmid_cfg->type); + + return PQOS_RETVAL_PARAM; + } + + return PQOS_RETVAL_ERROR; +} +#endif + +/* + * ======================================= + * ======================================= + * + * Monitoring + * + * ======================================= + * ======================================= + */ + +/** + * @brief Scale event values to bytes + * + * Retrieve event scale factor and scale value to bytes + * + * @param [in] event event scale factor to retrieve + * @param [in] val value to be scaled + * + * @return scaled value + * @retval value in bytes + */ +static uint64_t +scale_event(const enum pqos_mon_event event, const uint64_t val) +{ + const struct pqos_cap *cap; + const struct pqos_monitor *pmon; + int ret; + + _pqos_cap_get(&cap, NULL); + + ASSERT(cap != NULL); + + ret = pqos_cap_get_event(cap, event, &pmon); + ASSERT(ret == PQOS_RETVAL_OK); + if (ret != PQOS_RETVAL_OK) + return val; + else + return val * pmon->scale_factor; +} + +/** + * @brief Associates core with RMID at register level + * + * This function doesn't acquire API lock + * and can be used internally when lock is already taken. + * + * @param lcore logical core id + * @param rmid resource monitoring ID + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +mon_assoc_set(const unsigned lcore, const pqos_rmid_t rmid) +{ + int ret = 0; + uint32_t reg = 0; + uint64_t val = 0; + + reg = PQOS_MSR_ASSOC; + ret = msr_read(lcore, reg, &val); + if (ret != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + val &= PQOS_MSR_ASSOC_QECOS_MASK; + val |= (uint64_t)(rmid & PQOS_MSR_ASSOC_RMID_MASK); + + ret = msr_write(lcore, reg, val); + if (ret != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + return PQOS_RETVAL_OK; +} + +/** + * @brief Reads \a lcore to RMID association + * + * @param lcore logical core id + * @param rmid place to store RMID \a lcore is assigned to + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + * @retval PQOS_RETVAL_ERROR on error + */ +static int +mon_assoc_get(const unsigned lcore, pqos_rmid_t *rmid) +{ + int ret = 0; + uint32_t reg = PQOS_MSR_ASSOC; + uint64_t val = 0; + + ASSERT(rmid != NULL); + + ret = msr_read(lcore, reg, &val); + if (ret != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + val &= PQOS_MSR_ASSOC_RMID_MASK; + *rmid = (pqos_rmid_t)val; + + return PQOS_RETVAL_OK; +} + +int +hw_mon_assoc_get(const unsigned lcore, pqos_rmid_t *rmid) +{ + int ret = PQOS_RETVAL_OK; + const struct pqos_cpuinfo *cpu; + + if (rmid == NULL) + return PQOS_RETVAL_PARAM; + + _pqos_cap_get(NULL, &cpu); + + ASSERT(cpu != NULL); + + ret = pqos_cpu_check_core(cpu, lcore); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; + + ret = mon_assoc_get(lcore, rmid); + + return ret; +} + +int +hw_mon_reset(void) +{ + int ret = PQOS_RETVAL_OK; + unsigned i; + const struct pqos_cpuinfo *cpu; + + _pqos_cap_get(NULL, &cpu); + + for (i = 0; i < cpu->num_cores; i++) { + int retval = mon_assoc_set(cpu->cores[i].lcore, RMID0); + + if (retval != PQOS_RETVAL_OK) + ret = retval; + } + + return ret; +} + +/** + * @brief Reads monitoring event data from given core + * + * This function doesn't acquire API lock. + * + * @param lcore logical core id + * @param rmid RMID to be read + * @param event monitoring event + * @param value place to store read value + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +mon_read(const unsigned lcore, + const pqos_rmid_t rmid, + const unsigned event, + uint64_t *value) +{ + int retries = 0, retval = PQOS_RETVAL_ERROR; + uint64_t val = 0; + uint64_t val_evtsel = 0; + int flag_wrt = 1; + + /** + * Set event selection register (RMID + event id) + */ + val_evtsel = ((uint64_t)rmid) & PQOS_MSR_MON_EVTSEL_RMID_MASK; + val_evtsel <<= PQOS_MSR_MON_EVTSEL_RMID_SHIFT; + val_evtsel |= ((uint64_t)event) & PQOS_MSR_MON_EVTSEL_EVTID_MASK; + + for (retries = 0; retries < 4; retries++) { + if (flag_wrt) { + if (msr_write(lcore, PQOS_MSR_MON_EVTSEL, val_evtsel) != + MACHINE_RETVAL_OK) + break; + } + if (msr_read(lcore, PQOS_MSR_MON_QMC, &val) != + MACHINE_RETVAL_OK) + break; + if ((val & PQOS_MSR_MON_QMC_ERROR) != 0ULL) { + /* Read back IA32_QM_EVTSEL register + * to check for content change. + */ + if (msr_read(lcore, PQOS_MSR_MON_EVTSEL, &val) != + MACHINE_RETVAL_OK) + break; + if (val != val_evtsel) { + flag_wrt = 1; + continue; + } + } + if ((val & PQOS_MSR_MON_QMC_UNAVAILABLE) != 0ULL) { + /** + * Waiting for monitoring data + */ + flag_wrt = 0; + continue; + } + retval = PQOS_RETVAL_OK; + break; + } + /** + * Store event value + */ + if (retval == PQOS_RETVAL_OK) + *value = (val & PQOS_MSR_MON_QMC_DATA_MASK); + else + LOG_WARN("Error reading event %u on core %u (RMID%u)!\n", event, + lcore, (unsigned)rmid); + + return retval; +} + +/** + * @brief Gives the difference between two values with regard to the possible + * overrun and counter length + * + * @param event event counter length to retrieve + * @param old_value previous value + * @param new_value current value + * + * @return difference between the two values + */ +static uint64_t +get_delta(const enum pqos_mon_event event, + const uint64_t old_value, + const uint64_t new_value) +{ + const struct pqos_cap *cap; + const struct pqos_monitor *pmon; + int ret; + uint64_t max_value = 1LLU << 24; + + _pqos_cap_get(&cap, NULL); + + ret = pqos_cap_get_event(cap, event, &pmon); + if (ret == PQOS_RETVAL_OK) + max_value = 1LLU << pmon->counter_length; + + if (old_value > new_value) + return (max_value - old_value) + new_value; + else + return new_value - old_value; +} + +/** + * @brief Sets up IA32 performance counters for IPC and LLC miss ratio events + * + * @param group monitoring data + * @param event mask of selected monitoring events + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +ia32_perf_counter_start(const struct pqos_mon_data *group, + const enum pqos_mon_event event) +{ + uint64_t global_ctrl_mask = 0; + unsigned i; + const unsigned *cores = group->cores; + const unsigned num_cores = group->num_cores; + + ASSERT(cores != NULL && num_cores > 0); + + if (!(event & (PQOS_PERF_EVENT_LLC_MISS | PQOS_PERF_EVENT_IPC))) + return PQOS_RETVAL_OK; + + if (event & PQOS_PERF_EVENT_IPC) + global_ctrl_mask |= (0x3ULL << 32); /**< fixed counters 0&1 */ + + if (event & PQOS_PERF_EVENT_LLC_MISS) + global_ctrl_mask |= 0x1ULL; /**< programmable counter 0 */ + + /** + * Fixed counters are used for IPC calculations. + * Programmable counters are used for LLC miss calculations. + * Let's check if they are in use. + */ + for (i = 0; i < num_cores; i++) { + uint64_t global_inuse = 0; + int ret; + + ret = msr_read(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, + &global_inuse); + if (ret != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + if (global_inuse & global_ctrl_mask) + LOG_WARN("Hijacking performance counters on core %u\n", + cores[i]); + } + + /** + * - Disable counters in global control and + * reset counter values to 0. + * - Program counters for desired events + * - Enable counters in global control + */ + for (i = 0; i < num_cores; i++) { + const uint64_t fixed_ctrl = 0x33ULL; /**< track usr + os */ + int ret; + + ret = msr_write(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, 0); + if (ret != MACHINE_RETVAL_OK) + break; + + if (event & PQOS_PERF_EVENT_IPC) { + ret = msr_write(cores[i], IA32_MSR_INST_RETIRED_ANY, 0); + if (ret != MACHINE_RETVAL_OK) + break; + ret = msr_write(cores[i], IA32_MSR_CPU_UNHALTED_THREAD, + 0); + if (ret != MACHINE_RETVAL_OK) + break; + ret = msr_write(cores[i], IA32_MSR_FIXED_CTR_CTRL, + fixed_ctrl); + if (ret != MACHINE_RETVAL_OK) + break; + } + + if (event & PQOS_PERF_EVENT_LLC_MISS) { + const uint64_t evtsel0_miss = + IA32_EVENT_LLC_MISS_MASK | + (IA32_EVENT_LLC_MISS_UMASK << 8) | (1ULL << 16) | + (1ULL << 17) | (1ULL << 22); + + ret = msr_write(cores[i], IA32_MSR_PMC0, 0); + if (ret != MACHINE_RETVAL_OK) + break; + ret = msr_write(cores[i], IA32_MSR_PERFEVTSEL0, + evtsel0_miss); + if (ret != MACHINE_RETVAL_OK) + break; + } + + ret = msr_write(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, + global_ctrl_mask); + if (ret != MACHINE_RETVAL_OK) + break; + } + + if (i < num_cores) + return PQOS_RETVAL_ERROR; + + return PQOS_RETVAL_OK; +} + +/** + * @brief Disables IA32 performance counters + * + * @param num_cores number of cores in \a cores table + * @param cores table with core id's + * @param event mask of selected monitoring events + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +ia32_perf_counter_stop(const unsigned num_cores, + const unsigned *cores, + const enum pqos_mon_event event) +{ + int retval = PQOS_RETVAL_OK; + unsigned i; + + ASSERT(cores != NULL && num_cores > 0); + + if (!(event & (PQOS_PERF_EVENT_LLC_MISS | PQOS_PERF_EVENT_IPC))) + return retval; + + for (i = 0; i < num_cores; i++) { + int ret = msr_write(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, 0); + + if (ret != MACHINE_RETVAL_OK) + retval = PQOS_RETVAL_ERROR; + } + return retval; +} + +/** + * @brief Start perf monitoring counters + * + * @param group monitoring structure + * @param event PQoS event type + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +hw_mon_start_perf(struct pqos_mon_data *group, enum pqos_mon_event event) +{ + int ret = PQOS_RETVAL_OK; + unsigned i; + enum pqos_mon_event hw_event = (enum pqos_mon_event)0; + + group->intl->perf.ctx = + malloc(sizeof(group->intl->perf.ctx[0]) * group->num_cores); + if (group->intl->perf.ctx == NULL) { + LOG_ERROR("Memory allocation failed\n"); + return PQOS_RETVAL_ERROR; + } + + for (i = 0; i < DIM(perf_event); i++) { + enum pqos_mon_event evt = perf_event[i]; + + if (event & evt) { +#ifdef __linux__ + if (perf_mon_is_event_supported(evt)) { + ret = perf_mon_start(group, evt); + if (ret != PQOS_RETVAL_OK) + return ret; + group->intl->perf.event |= evt; + continue; + } +#endif + hw_event |= evt; + } + } + + if (!group->intl->perf.event) { + free(group->intl->perf.ctx); + group->intl->perf.ctx = NULL; + } + + /* Start IA32 performance counters */ + if (hw_event) { + ret = ia32_perf_counter_start(group, hw_event); + if (ret == PQOS_RETVAL_OK) + group->intl->hw.event |= hw_event; + } + + return ret; +} + +/** + * @brief Stop perf monitoring counters + * + * @param group monitoring structure + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +hw_mon_stop_perf(struct pqos_mon_data *group) +{ + int ret = PQOS_RETVAL_OK; + unsigned i; + enum pqos_mon_event hw_event = (enum pqos_mon_event)0; + + for (i = 0; i < DIM(perf_event); i++) { + enum pqos_mon_event evt = perf_event[i]; + +#ifdef __linux__ + /* Stop perf event */ + if (group->intl->perf.event & evt) { + ret = perf_mon_stop(group, evt); + if (ret != PQOS_RETVAL_OK) + return ret; + continue; + } +#endif + + if (group->intl->hw.event & evt) + hw_event |= evt; + } + + /* Stop IA32 performance counters */ + if (hw_event) { + ret = ia32_perf_counter_stop(group->num_cores, group->cores, + group->event); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; + } + + if (group->intl->perf.ctx != NULL) { + free(group->intl->perf.ctx); + group->intl->perf.ctx = NULL; + } + + return ret; +} + +/** + * @brief Start HW monitoring counters + * + * @param group monitoring structure + * @param event PQoS event type + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +hw_mon_start_counter(struct pqos_mon_data *group, enum pqos_mon_event event) +{ + const unsigned num_cores = group->num_cores; + const struct pqos_cpuinfo *cpu; + unsigned core2cluster[num_cores]; + struct pqos_mon_poll_ctx ctxs[num_cores]; + unsigned num_ctxs = 0; + unsigned i; + int ret = PQOS_RETVAL_OK; + enum pqos_mon_event ctx_event = (enum pqos_mon_event)( + event & (PQOS_MON_EVENT_L3_OCCUP | PQOS_MON_EVENT_LMEM_BW | + PQOS_MON_EVENT_TMEM_BW | PQOS_MON_EVENT_RMEM_BW)); + + _pqos_cap_get(NULL, &cpu); + + memset(ctxs, 0, sizeof(ctxs)); + + /* + * Initialize poll context table: + * - get core cluster + * - allocate RMID + */ + for (i = 0; i < group->num_cores; i++) { + const unsigned lcore = group->cores[i]; + unsigned j; + unsigned cluster = 0; + + ret = pqos_cpu_get_clusterid(cpu, lcore, &cluster); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; + core2cluster[i] = cluster; + + for (j = 0; j < num_ctxs; j++) + if (ctxs[j].lcore == lcore || + ctxs[j].cluster == cluster) + break; + + if (j >= num_ctxs) { + /** + * New cluster is found + * - save cluster id in the table + * - allocate RMID for the cluster + */ + ctxs[num_ctxs].lcore = lcore; + ctxs[num_ctxs].cluster = cluster; +#ifdef PQOS_RMID_CUSTOM + ret = rmid_alloc_custom(&ctxs[num_ctxs], ctx_event, + &rmid_cfg); +#else + ret = rmid_alloc(&ctxs[num_ctxs], ctx_event); +#endif + if (ret != PQOS_RETVAL_OK) + return ret; + + num_ctxs++; + } + } + + group->intl->hw.ctx = (struct pqos_mon_poll_ctx *)malloc( + sizeof(group->intl->hw.ctx[0]) * num_ctxs); + if (group->intl->hw.ctx == NULL) + return PQOS_RETVAL_RESOURCE; + + /** + * Associate requested cores with + * the allocated RMID + */ + group->num_cores = num_cores; + for (i = 0; i < num_cores; i++) { + unsigned cluster, j; + pqos_rmid_t rmid; + + cluster = core2cluster[i]; + for (j = 0; j < num_ctxs; j++) + if (ctxs[j].cluster == cluster) + break; + if (j >= num_ctxs) { + ret = PQOS_RETVAL_ERROR; + goto hw_mon_start_counter_exit; + } + rmid = ctxs[j].rmid; + + ret = mon_assoc_set(group->cores[i], rmid); + if (ret != PQOS_RETVAL_OK) + goto hw_mon_start_counter_exit; + } + + group->intl->hw.num_ctx = num_ctxs; + for (i = 0; i < num_ctxs; i++) + group->intl->hw.ctx[i] = ctxs[i]; + + group->intl->hw.event |= ctx_event; + +hw_mon_start_counter_exit: + if (ret != PQOS_RETVAL_OK) { + for (i = 0; i < num_cores; i++) + (void)mon_assoc_set(group->cores[i], RMID0); + + if (group->intl->hw.ctx != NULL) + free(group->intl->hw.ctx); + } + + return ret; +} + +int +hw_mon_start(const unsigned num_cores, + const unsigned *cores, + const enum pqos_mon_event event, + void *context, + struct pqos_mon_data *group) +{ + unsigned i; + int ret = PQOS_RETVAL_OK; + int retval = PQOS_RETVAL_OK; + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + enum pqos_mon_event req_events; + enum pqos_mon_event started_evts = (enum pqos_mon_event)0; + + ASSERT(group != NULL); + ASSERT(cores != NULL); + ASSERT(num_cores > 0); + ASSERT(event > 0); + + _pqos_cap_get(&cap, &cpu); + + req_events = event; + + if (req_events & PQOS_MON_EVENT_RMEM_BW) + req_events |= (enum pqos_mon_event)(PQOS_MON_EVENT_LMEM_BW | + PQOS_MON_EVENT_TMEM_BW); + if (req_events & PQOS_PERF_EVENT_IPC) + req_events |= (enum pqos_mon_event)( + PQOS_PERF_EVENT_CYCLES | PQOS_PERF_EVENT_INSTRUCTIONS); + + /** + * Validate if event is listed in capabilities + */ + for (i = 0; i < (sizeof(event) * 8); i++) { + const enum pqos_mon_event evt_mask = + (enum pqos_mon_event)(1U << i); + const struct pqos_monitor *ptr = NULL; + + if (!(evt_mask & event)) + continue; + + retval = pqos_cap_get_event(cap, evt_mask, &ptr); + if (retval != PQOS_RETVAL_OK || ptr == NULL) + return PQOS_RETVAL_PARAM; + } + + /** + * Check if all requested cores are valid + * and not used by other monitoring processes. + * + * Check if any of requested cores is already subject to monitoring + * within this process. + */ + for (i = 0; i < num_cores; i++) { + const unsigned lcore = cores[i]; + pqos_rmid_t rmid = RMID0; + + ret = pqos_cpu_check_core(cpu, lcore); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; + + ret = mon_assoc_get(lcore, &rmid); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; + + if (rmid != RMID0) { + /* If not RMID0 then it is already monitored */ + LOG_INFO("Core %u is already monitored with " + "RMID%u.\n", + lcore, rmid); + return PQOS_RETVAL_RESOURCE; + } + } + + /** + * Fill in the monitoring group structure + */ + group->event = event; + group->context = context; + group->num_cores = num_cores; + group->cores = (unsigned *)malloc(sizeof(group->cores[0]) * num_cores); + if (group->cores == NULL) + return PQOS_RETVAL_RESOURCE; + for (i = 0; i < group->num_cores; i++) + group->cores[i] = cores[i]; + + /* start perf events */ + retval = hw_mon_start_perf(group, req_events); + if (retval != PQOS_RETVAL_OK) + goto pqos_mon_start_error; + + /* start MBM/CMT events */ + retval = hw_mon_start_counter(group, req_events); + if (retval != PQOS_RETVAL_OK) + goto pqos_mon_start_error; + + started_evts |= group->intl->perf.event; + started_evts |= group->intl->hw.event; + + /** + * All events required by RMEM has been started + */ + if ((started_evts & PQOS_MON_EVENT_LMEM_BW) && + (started_evts & PQOS_MON_EVENT_TMEM_BW)) { + group->values.mbm_remote = 0; + started_evts |= (enum pqos_mon_event)PQOS_MON_EVENT_RMEM_BW; + } + + /** + * All events required by IPC has been started + */ + if ((started_evts & PQOS_PERF_EVENT_CYCLES) && + (started_evts & PQOS_PERF_EVENT_INSTRUCTIONS)) { + group->values.ipc = 0; + started_evts |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC; + } + + /* Check if all selected events were started */ + if ((group->event & started_evts) != group->event) { + LOG_ERROR("Failed to start all selected " + "HW monitoring events\n"); + retval = PQOS_RETVAL_ERROR; + } + +pqos_mon_start_error: + if (retval != PQOS_RETVAL_OK) { + hw_mon_stop_perf(group); + + if (group->cores != NULL) + free(group->cores); + } + + return retval; +} + +int +hw_mon_stop(struct pqos_mon_data *group) +{ + int ret = PQOS_RETVAL_OK; + int retval = PQOS_RETVAL_OK; + unsigned i = 0; + const struct pqos_cpuinfo *cpu; + + ASSERT(group != NULL); + + if (group->num_cores == 0 || group->cores == NULL || + group->intl->hw.num_ctx == 0 || group->intl->hw.ctx == NULL) { + return PQOS_RETVAL_PARAM; + } + + _pqos_cap_get(NULL, &cpu); + + for (i = 0; i < group->intl->hw.num_ctx; i++) { + /** + * Validate core list in the group structure is correct + */ + const unsigned lcore = group->intl->hw.ctx[i].lcore; + pqos_rmid_t rmid = RMID0; + + ret = pqos_cpu_check_core(cpu, lcore); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; + ret = mon_assoc_get(lcore, &rmid); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; + if (rmid != group->intl->hw.ctx[i].rmid) + LOG_WARN("Core %u RMID association changed from %u " + "to %u! The core has been hijacked!\n", + lcore, group->intl->hw.ctx[i].rmid, rmid); + } + + for (i = 0; i < group->num_cores; i++) { + /** + * Associate cores from the group back with RMID0 + */ + ret = mon_assoc_set(group->cores[i], RMID0); + if (ret != PQOS_RETVAL_OK) + retval = PQOS_RETVAL_RESOURCE; + } + + /* stop perf counters */ + ret = hw_mon_stop_perf(group); + if (ret != PQOS_RETVAL_OK) + retval = ret; + + /** + * Free poll contexts, core list and clear the group structure + */ + free(group->cores); + free(group->intl->hw.ctx); + memset(group, 0, sizeof(*group)); + + return retval; +} + +/** + * @brief Read HW counter + * + * Reads counters for all events and stores values + * + * @param group monitoring structure + * @param event PQoS event + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + * @retval PQOS_RETVAL_ERROR if error occurs + */ +static int +hw_mon_read_counter(struct pqos_mon_data *group, + const enum pqos_mon_event event) +{ + struct pqos_event_values *pv = &group->values; + uint64_t value = 0; + uint64_t max_value = 1LLU << 24; + const struct pqos_cap *cap; + const struct pqos_monitor *pmon; + unsigned i; + int ret; + + ASSERT(event == PQOS_MON_EVENT_L3_OCCUP || + event == PQOS_MON_EVENT_LMEM_BW || + event == PQOS_MON_EVENT_TMEM_BW); + + _pqos_cap_get(&cap, NULL); + + ret = pqos_cap_get_event(cap, event, &pmon); + if (ret == PQOS_RETVAL_OK) + max_value = 1LLU << pmon->counter_length; + + for (i = 0; i < group->intl->hw.num_ctx; i++) { + uint64_t tmp = 0; + const unsigned lcore = group->intl->hw.ctx[i].lcore; + const pqos_rmid_t rmid = group->intl->hw.ctx[i].rmid; + int retval; + + retval = mon_read(lcore, rmid, get_event_id(event), &tmp); + if (retval != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + + value += tmp; + + if (value >= max_value) + value -= max_value; + } + + switch (event) { + case PQOS_MON_EVENT_L3_OCCUP: + pv->llc = scale_event(PQOS_MON_EVENT_L3_OCCUP, value); + break; + case PQOS_MON_EVENT_LMEM_BW: + if (group->intl->valid_mbm_read) { + pv->mbm_local_delta = + get_delta(event, pv->mbm_local, value); + pv->mbm_local_delta = + scale_event(event, pv->mbm_local_delta); + } else + /* Report zero memory bandwidth with first read */ + pv->mbm_local_delta = 0; + pv->mbm_local = value; + break; + case PQOS_MON_EVENT_TMEM_BW: + if (group->intl->valid_mbm_read) { + pv->mbm_total_delta = + get_delta(event, pv->mbm_total, value); + pv->mbm_total_delta = + scale_event(event, pv->mbm_total_delta); + } else + /* Report zero memory bandwidth with first read */ + pv->mbm_total_delta = 0; + pv->mbm_total = value; + break; + default: + return PQOS_RETVAL_PARAM; + } + + return PQOS_RETVAL_OK; +} + +/** + * @brief Read HW perf counter + * + * @param group monitoring structure + * @param event PQoS event + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + * @retval PQOS_RETVAL_ERROR if error occurs + */ +static int +hw_mon_read_perf(struct pqos_mon_data *group, const enum pqos_mon_event event) +{ + struct pqos_event_values *pv = &group->values; + uint64_t val = 0; + unsigned n; + uint64_t reg; + uint64_t *value; + uint64_t *delta; + + switch (event) { + case (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS: + reg = IA32_MSR_INST_RETIRED_ANY; + value = &pv->ipc_retired; + delta = &pv->ipc_retired_delta; + break; + case (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES: + reg = IA32_MSR_CPU_UNHALTED_THREAD; + value = &pv->ipc_unhalted; + delta = &pv->ipc_unhalted_delta; + break; + case PQOS_PERF_EVENT_LLC_MISS: + reg = IA32_MSR_PMC0; + value = &pv->llc_misses; + delta = &pv->llc_misses_delta; + break; + default: + return PQOS_RETVAL_PARAM; + } + + /** + * If multiple cores monitored in one group + * then we have to accumulate the values in the group. + */ + for (n = 0; n < group->num_cores; n++) { + uint64_t tmp = 0; + int ret = msr_read(group->cores[n], reg, &tmp); + + if (ret != MACHINE_RETVAL_OK) + return PQOS_RETVAL_ERROR; + val += tmp; + } + + *delta = val - *value; + *value = val; + + return PQOS_RETVAL_OK; +} + +int +hw_mon_poll(struct pqos_mon_data *group, const enum pqos_mon_event event) +{ + int ret = PQOS_RETVAL_OK; + + switch (event) { + case PQOS_MON_EVENT_L3_OCCUP: + case PQOS_MON_EVENT_LMEM_BW: + case PQOS_MON_EVENT_TMEM_BW: + ret = hw_mon_read_counter(group, event); + if (ret != PQOS_RETVAL_OK) + goto pqos_core_poll__exit; + break; + case (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES: + case (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS: + case PQOS_PERF_EVENT_LLC_MISS: + ret = hw_mon_read_perf(group, event); + if (ret != PQOS_RETVAL_OK) + goto pqos_core_poll__exit; + break; + default: + ret = PQOS_RETVAL_PARAM; + } + +pqos_core_poll__exit: + return ret; +} +/* + * ======================================= + * ======================================= + * + * Small utils + * + * ======================================= + * ======================================= + */ + +/** + * @brief Maps PQoS API event onto an MSR event id + * + * @param [in] event PQoS API event id + * + * @return MSR event id + * @retval 0 if not successful + */ +static unsigned +get_event_id(const enum pqos_mon_event event) +{ + switch (event) { + case PQOS_MON_EVENT_L3_OCCUP: + return 1; + break; + case PQOS_MON_EVENT_LMEM_BW: + return 3; + break; + case PQOS_MON_EVENT_TMEM_BW: + return 2; + break; + case PQOS_MON_EVENT_RMEM_BW: + default: + ASSERT(0); /**< this means bug */ + break; + } + return 0; +} diff -Nru intel-cmt-cat-3.2/lib/hw_monitoring.h intel-cmt-cat-4.0/lib/hw_monitoring.h --- intel-cmt-cat-3.2/lib/hw_monitoring.h 1970-01-01 00:00:00.000000000 +0000 +++ intel-cmt-cat-4.0/lib/hw_monitoring.h 2020-06-19 10:42:55.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * BSD LICENSE + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.O + * + */ + +/** + * @brief Internal header file to PQoS HW monitoring module + */ +#ifndef __PQOS_HW_MON_H__ +#define __PQOS_HW_MON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pqos.h" + +/** + * @brief Initializes hardware monitoring sub-module of the library (CMT) + * + * @param cpu cpu topology structure + * @param cap capabilities structure + * @param cfg library configuration structure + * + * @return Operation status + * @retval PQOS_RETVAL_OK success + */ +int hw_mon_init(const struct pqos_cpuinfo *cpu, + const struct pqos_cap *cap, + const struct pqos_config *cfg); + +/** + * @brief Shuts down hardware monitoring sub-module of the library + * + * @return Operation status + */ +int hw_mon_fini(void); + +/** + * @brief Hardware interface to reset monitoring by binding all cores with RMID0 + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int hw_mon_reset(void); + +/** + * @brief Hardware interface to read RMID association of the \a lcore + * + * @param [in] lcore CPU logical core id + * @param [out] rmid place to store resource monitoring id + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int hw_mon_assoc_get(const unsigned lcore, pqos_rmid_t *rmid); + +/** + * @brief Hardware interface to start resource monitoring on selected + * group of cores + * + * The function sets up content of the \a group structure. + * + * Note that \a event cannot select PQOS_PERF_EVENT_IPC or + * PQOS_PERF_EVENT_L3_MISS events without any PQoS event + * selected at the same time. + * + * @param [in] num_cores number of cores in \a cores array + * @param [in] cores array of logical core id's + * @param [in] event combination of monitoring events + * @param [in] context a pointer for application's convenience + * (unused by the library) + * @param [in,out] group a pointer to monitoring structure + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int hw_mon_start(const unsigned num_cores, + const unsigned *cores, + const enum pqos_mon_event event, + void *context, + struct pqos_mon_data *group); + +/** + * @brief Hardware interface to stop resource monitoring data for selected + * monitoring group + * + * @param [in] group monitoring context for selected number of cores + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int hw_mon_stop(struct pqos_mon_data *group); + +/** + * @brief Hardware interface poll monitoring data + * + * Reads counters for all events and stores values + * + * @param group monitoring structure + * @param event PQoS event type + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + * @retval PQOS_RETVAL_ERROR if error occurs + */ +int hw_mon_poll(struct pqos_mon_data *group, const enum pqos_mon_event event); + +#ifdef __cplusplus +} +#endif + +#endif /* __PQOS_HW_MON_H__ */ diff -Nru intel-cmt-cat-3.2/lib/lib_doxygen.cfg intel-cmt-cat-4.0/lib/lib_doxygen.cfg --- intel-cmt-cat-3.2/lib/lib_doxygen.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/lib_doxygen.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ # # BSD LICENSE # -# Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/log.c intel-cmt-cat-4.0/lib/log.c --- intel-cmt-cat-3.2/lib/log.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/log.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ * Local data types * --------------------------------------- */ -#define AP_BUFFER_SIZE 256 +#define AP_BUFFER_SIZE 256 /** * --------------------------------------- @@ -59,21 +59,20 @@ * --------------------------------------- */ -static int m_opt = 0; /**< log options */ -static int m_fd = -1; /**< log file descriptor */ -static void *m_context_log = NULL; /**< log callback context */ +static int m_opt = 0; /**< log options */ +static int m_fd = -1; /**< log file descriptor */ +static void *m_context_log = NULL; /**< log callback context */ /** * log callback */ static void (*m_callback_log)(void *, const size_t, const char *); -static int log_init_successful = 0; /**< log init gatekeeper */ +static int log_init_successful = 0; /**< log init gatekeeper */ /** * --------------------------------------- * Local functions * --------------------------------------- */ - /** * ======================================= * initialize and shutdown @@ -81,17 +80,19 @@ */ int -log_init(int fd_log, void (*callback_log)(void *, const size_t, const char *), - void *context_log, int verbosity) +log_init(int fd_log, + void (*callback_log)(void *, const size_t, const char *), + void *context_log, + int verbosity) { - /** + /** * Set log message verbosity */ switch (verbosity) { case LOG_VER_SILENT: m_opt = LOG_OPT_SILENT; log_init_successful = 1; - return LOG_RETVAL_OK; + return LOG_RETVAL_OK; case LOG_VER_DEFAULT: m_opt = LOG_OPT_DEFAULT; break; @@ -106,16 +107,15 @@ break; } - if (fd_log < 0 && callback_log == NULL) { - fprintf(stderr, "%s: no LOG destination selected\n", - __func__); + if (fd_log < 0 && callback_log == NULL) { + fprintf(stderr, "%s: no LOG destination selected\n", __func__); return LOG_RETVAL_ERROR; } - m_fd = fd_log; - m_callback_log = callback_log; - m_context_log = context_log; - log_init_successful = 1; + m_fd = fd_log; + m_callback_log = callback_log; + m_context_log = context_log; + log_init_successful = 1; return LOG_RETVAL_OK; } @@ -123,16 +123,16 @@ int log_fini(void) { - if (m_opt == LOG_OPT_SILENT) { + if (m_opt == LOG_OPT_SILENT) { log_init_successful = 0; - return LOG_RETVAL_OK; + return LOG_RETVAL_OK; } m_opt = 0; - m_fd = -1; - m_callback_log = NULL; - m_context_log = NULL; - log_init_successful = 0; + m_fd = -1; + m_callback_log = NULL; + m_context_log = NULL; + log_init_successful = 0; return LOG_RETVAL_OK; } @@ -141,17 +141,17 @@ log_printf(int type, const char *str, ...) { va_list ap; - char ap_buffer[AP_BUFFER_SIZE]; + char ap_buffer[AP_BUFFER_SIZE]; int size; - /* If log_init has not been successful then - * log_printf should not work. */ + /* If log_init has not been successful then + * log_printf should not work. */ ASSERT(log_init_successful == 1); - if (log_init_successful == 0) - return; + if (log_init_successful == 0) + return; - if (m_opt == LOG_OPT_SILENT) - return; + if (m_opt == LOG_OPT_SILENT) + return; if ((m_opt & type) == 0) return; @@ -160,20 +160,20 @@ if (str == NULL) return; - va_start(ap, str); - ap_buffer[AP_BUFFER_SIZE - 1] = '\0'; - size = vsnprintf(ap_buffer, AP_BUFFER_SIZE - 1, str, ap); - va_end(ap); - ASSERT(size >= 0); - if (size < 0) - return; - - if (m_callback_log != NULL) - m_callback_log(m_context_log, size, ap_buffer); - - if (m_fd >= 0) { - if (write(m_fd, ap_buffer, size) < 0) - fprintf(stderr, "%s: printing to file failed\n", + va_start(ap, str); + ap_buffer[AP_BUFFER_SIZE - 1] = '\0'; + size = vsnprintf(ap_buffer, AP_BUFFER_SIZE - 1, str, ap); + va_end(ap); + ASSERT(size >= 0); + if (size < 0) + return; + + if (m_callback_log != NULL) + m_callback_log(m_context_log, size, ap_buffer); + + if (m_fd >= 0) { + if (write(m_fd, ap_buffer, size) < 0) + fprintf(stderr, "%s: printing to file failed\n", __func__); - } + } } diff -Nru intel-cmt-cat-3.2/lib/log.h intel-cmt-cat-4.0/lib/log.h --- intel-cmt-cat-3.2/lib/log.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/log.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,24 +46,24 @@ extern "C" { #endif -#define LOG_VER_SILENT (-1) -#define LOG_VER_DEFAULT (0) -#define LOG_VER_VERBOSE (1) -#define LOG_VER_SUPER_VERBOSE (2) - -#define LOG_RETVAL_OK 0 /**< everything OK */ -#define LOG_RETVAL_ERROR 1 /**< generic error */ - -#define LOG_OPT_INFO (1 << 0) -#define LOG_OPT_WARN (1 << 1) -#define LOG_OPT_ERROR (1 << 2) -#define LOG_OPT_DEBUG (1 << 3) - -#define LOG_OPT_SILENT (-1) -#define LOG_OPT_DEFAULT (LOG_OPT_WARN|LOG_OPT_ERROR) -#define LOG_OPT_VERBOSE (LOG_OPT_WARN|LOG_OPT_ERROR|LOG_OPT_INFO) -#define LOG_OPT_SUPER_VERBOSE (LOG_OPT_WARN|LOG_OPT_ERROR|LOG_OPT_INFO| \ - LOG_OPT_DEBUG) +#define LOG_VER_SILENT (-1) +#define LOG_VER_DEFAULT (0) +#define LOG_VER_VERBOSE (1) +#define LOG_VER_SUPER_VERBOSE (2) + +#define LOG_RETVAL_OK 0 /**< everything OK */ +#define LOG_RETVAL_ERROR 1 /**< generic error */ + +#define LOG_OPT_INFO (1 << 0) +#define LOG_OPT_WARN (1 << 1) +#define LOG_OPT_ERROR (1 << 2) +#define LOG_OPT_DEBUG (1 << 3) + +#define LOG_OPT_SILENT (-1) +#define LOG_OPT_DEFAULT (LOG_OPT_WARN | LOG_OPT_ERROR) +#define LOG_OPT_VERBOSE (LOG_OPT_WARN | LOG_OPT_ERROR | LOG_OPT_INFO) +#define LOG_OPT_SUPER_VERBOSE \ + (LOG_OPT_WARN | LOG_OPT_ERROR | LOG_OPT_INFO | LOG_OPT_DEBUG) #define LOG_INFO(str...) log_printf(LOG_OPT_INFO, "INFO: " str) #define LOG_WARN(str...) log_printf(LOG_OPT_WARN, "WARN: " str) @@ -104,9 +104,9 @@ * @retval LOG_RETVAL_OK on success */ int log_init(int fd_log, - void (*callback_log)(void *, const size_t, const char *), - void *context_log, - int verbosity); + void (*callback_log)(void *, const size_t, const char *), + void *context_log, + int verbosity); /** * @brief Shuts down PQoS log module diff -Nru intel-cmt-cat-3.2/lib/machine.c intel-cmt-cat-4.0/lib/machine.c --- intel-cmt-cat-3.2/lib/machine.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/machine.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,9 +55,9 @@ #include "machine.h" #include "log.h" -static int *m_msr_fd = NULL; /**< MSR driver file descriptors table */ -static unsigned m_maxcores = 0; /**< max number of cores (size of the - table above too) */ +static int *m_msr_fd = NULL; /**< MSR driver file descriptors table */ +static unsigned m_maxcores = 0; /**< max number of cores (size of the + table above too) */ int machine_init(const unsigned max_core_id) @@ -113,9 +113,7 @@ } void -lcpuid(const unsigned leaf, - const unsigned subleaf, - struct cpuid_out *out) +lcpuid(const unsigned leaf, const unsigned subleaf, struct cpuid_out *out) { ASSERT(out != NULL); if (out == NULL) @@ -129,9 +127,9 @@ "mov %%ebx, %1\n\t" "mov %%ecx, %2\n\t" "mov %%edx, %3\n\t" - : "=g" (out->eax), "=g" (out->ebx), "=g" (out->ecx), - "=g" (out->edx) - : "g" (leaf), "g" (subleaf) + : "=g"(out->eax), "=g"(out->ebx), "=g"(out->ecx), + "=g"(out->edx) + : "g"(leaf), "g"(subleaf) : "%eax", "%ebx", "%ecx", "%edx"); #else asm volatile("push %%ebx\n\t" @@ -143,9 +141,9 @@ "mov %%ecx, %2\n\t" "mov %%edx, %3\n\t" "pop %%ebx\n\t" - : "=g" (out->eax), "=g" (out->ebx), "=g" (out->ecx), - "=g" (out->edx) - : "g" (leaf), "g" (subleaf) + : "=g"(out->eax), "=g"(out->ebx), "=g"(out->ecx), + "=g"(out->edx) + : "g"(leaf), "g"(subleaf) : "%eax", "%ecx", "%edx"); #endif } @@ -173,12 +171,10 @@ memset(fname, 0, sizeof(fname)); #ifdef __linux__ - snprintf(fname, sizeof(fname)-1, - "/dev/cpu/%u/msr", lcore); + snprintf(fname, sizeof(fname) - 1, "/dev/cpu/%u/msr", lcore); #endif #ifdef __FreeBSD__ - snprintf(fname, sizeof(fname)-1, - "/dev/cpuctl%u", lcore); + snprintf(fname, sizeof(fname) - 1, "/dev/cpuctl%u", lcore); #endif fd = open(fname, O_RDWR); if (fd < 0) @@ -191,9 +187,7 @@ } int -msr_read(const unsigned lcore, - const uint32_t reg, - uint64_t *value) +msr_read(const unsigned lcore, const uint32_t reg, uint64_t *value) { int ret = MACHINE_RETVAL_OK; int fd = -1; @@ -241,9 +235,7 @@ } int -msr_write(const unsigned lcore, - const uint32_t reg, - const uint64_t value) +msr_write(const unsigned lcore, const uint32_t reg, const uint64_t value) { int ret = MACHINE_RETVAL_OK; int fd = -1; diff -Nru intel-cmt-cat-3.2/lib/machine.h intel-cmt-cat-4.0/lib/machine.h --- intel-cmt-cat-3.2/lib/machine.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/machine.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,14 +47,14 @@ extern "C" { #endif -#define MACHINE_DEFAULT_MAX_COREID 255 /**< max core id */ +#define MACHINE_DEFAULT_MAX_COREID 255 /**< max core id */ -#define MACHINE_RETVAL_OK 0 /**< everything OK */ -#define MACHINE_RETVAL_ERROR 1 /**< generic error */ -#define MACHINE_RETVAL_PARAM 2 /**< parameter error */ +#define MACHINE_RETVAL_OK 0 /**< everything OK */ +#define MACHINE_RETVAL_ERROR 1 /**< generic error */ +#define MACHINE_RETVAL_PARAM 2 /**< parameter error */ /* cpuid leaf for cache topology */ -#define CPUID_LEAF_CACHE 4 +#define CPUID_LEAF_CACHE 4 /** * Results of CPUID operation are stored in this structure. @@ -94,10 +94,7 @@ * @param [in] subleaf CPUID sub-leaf number * @param [out] out structure to write CPUID results into */ -void -lcpuid(const unsigned leaf, - const unsigned subleaf, - struct cpuid_out *out); +void lcpuid(const unsigned leaf, const unsigned subleaf, struct cpuid_out *out); /** * @brief Executes RDMSR on \a lcore logical core @@ -109,10 +106,7 @@ * @return Operation status * @retval MACHINE_RETVAL_OK on success */ -int -msr_read(const unsigned lcore, - const uint32_t reg, - uint64_t *value); +int msr_read(const unsigned lcore, const uint32_t reg, uint64_t *value); /** * @brief Executes WRMSR on \a lcore logical core @@ -124,10 +118,7 @@ * @return Operation status * @retval MACHINE_RETVAL_OK on success */ -int -msr_write(const unsigned lcore, - const uint32_t reg, - const uint64_t value); +int msr_write(const unsigned lcore, const uint32_t reg, const uint64_t value); #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/lib/Makefile intel-cmt-cat-4.0/lib/Makefile --- intel-cmt-cat-3.2/lib/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,8 +35,8 @@ ############################################################################### LIB = libpqos -VERSION = 3.2.0 -SO_VERSION = 3 +VERSION = 4.0.0 +SO_VERSION = 4 SHARED ?= y LDFLAGS = -L. -lpthread -z noexecstack -z relro -z now CFLAGS = -pthread -I./ -D_GNU_SOURCE \ @@ -210,6 +210,8 @@ -f cap.h -f cap.c \ -f common.h -f common.c \ -f cpuinfo.h -f cpuinfo.c \ + -f hw_cap.h -f hw_cap.c \ + -f hw_monitoring.h hw_monitoring.c \ -f log.h -f log.c \ -f machine.h -f machine.c \ -f monitoring.h -f monitoring.c \ @@ -226,11 +228,12 @@ -f types.h \ -f utils.h -f utils.c +CLANGFORMAT?=clang-format .PHONY: clang-format clang-format: - @for file in "pqos.h" $(wildcard resctrl*.[ch]); do \ + @for file in $(wildcard *.[ch]); do \ echo "Checking style $$file"; \ - clang-format -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ + $(CLANGFORMAT) -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ { echo "ERROR: $$file has style problems"; exit 1; } \ done @@ -251,6 +254,8 @@ log.c log.h types.h machine.c machine.h \ utils.c utils.h \ cpuinfo.c cpuinfo.h os_allocation.h os_allocation.c \ + hw_cap.h hw_cap.c \ + hw_monitoring.h hw_monitoring.c \ os_cap.h os_cap.c \ os_monitoring.h os_monitoring.c \ perf_monitoring.h perf_monitoring.c \ diff -Nru intel-cmt-cat-3.2/lib/monitoring.c intel-cmt-cat-4.0/lib/monitoring.c --- intel-cmt-cat-3.2/lib/monitoring.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/monitoring.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,27 +31,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * @brief Implementation of PQoS monitoring API. - * - * CPUID and MSR operations are done on 'local' system. - * - */ - -#include -#include -#include -#include - #include "pqos.h" #include "cap.h" #include "monitoring.h" #include "os_monitoring.h" +#include "hw_monitoring.h" +#include "perf_monitoring.h" +#ifdef __linux__ +#include "resctrl.h" +#include "resctrl_monitoring.h" +#endif -#include "machine.h" #include "types.h" #include "log.h" -#include "cpu_registers.h" /** * --------------------------------------- @@ -60,20 +52,6 @@ */ /** - * Special RMID - after reset all cores are associated with it. - * - * The assumption is that if core is not assigned to it - * then it is subject of monitoring activity by a different process. - */ -#define RMID0 (0) - -/** - * Max value of the memory bandwidth data = 2^24 - * assuming there is 24 bit space available - */ -#define MBM_MAX_VALUE (1 << 24) - -/** * --------------------------------------- * Local data types * --------------------------------------- @@ -84,14 +62,6 @@ * Local data structures * --------------------------------------- */ -static const struct pqos_cpuinfo *m_cpu = NULL; /**< cpu topology passed - from cap */ -static unsigned m_rmid_max = 0; /**< max RMID */ -#ifdef PQOS_RMID_CUSTOM -/** Custom RMID configuration */ -static struct pqos_rmid_config rmid_cfg = {PQOS_RMID_TYPE_DEFAULT, - {0, NULL, NULL} }; -#endif #ifdef __linux__ static int m_interface = PQOS_INTER_MSR; #endif @@ -101,32 +71,6 @@ * --------------------------------------- */ -static int -mon_assoc_set(const unsigned lcore, - const pqos_rmid_t rmid); - -static int -mon_assoc_get(const unsigned lcore, - pqos_rmid_t *rmid); - -static int -mon_read(const unsigned lcore, - const pqos_rmid_t rmid, - const enum pqos_mon_event event, - uint64_t *value); - -static int -pqos_core_poll(struct pqos_mon_data *group); - -static unsigned -get_event_id(const enum pqos_mon_event event); - -static uint64_t -get_delta(const uint64_t old_value, const uint64_t new_value); - -static uint64_t -scale_event(const enum pqos_mon_event event, const uint64_t val); - /* * ======================================= * ======================================= @@ -137,7 +81,6 @@ * ======================================= */ - int pqos_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap, @@ -159,50 +102,20 @@ } ASSERT(item != NULL); - m_rmid_max = item->u.mon->max_rmid; - if (cfg->interface == PQOS_INTER_MSR && m_rmid_max == 0) { - pqos_mon_fini(); - return PQOS_RETVAL_PARAM; - } - LOG_DEBUG("Max RMID per monitoring cluster is %u\n", m_rmid_max); #ifdef __linux__ if (cfg->interface == PQOS_INTER_OS || - cfg->interface == PQOS_INTER_OS_RESCTRL_MON) + cfg->interface == PQOS_INTER_OS_RESCTRL_MON) ret = os_mon_init(cpu, cap); if (ret != PQOS_RETVAL_OK) return ret; #endif + if (cfg->interface == PQOS_INTER_MSR) + ret = hw_mon_init(cpu, cap, cfg); -#ifdef PQOS_RMID_CUSTOM - rmid_cfg.type = cfg->rmid_cfg.type; - if (cfg->rmid_cfg.type == PQOS_RMID_TYPE_MAP) { - const unsigned num = cfg->rmid_cfg.map.num; - unsigned i; - - if (cfg->rmid_cfg.map.core == NULL || - cfg->rmid_cfg.map.rmid == NULL) { - pqos_mon_fini(); - return PQOS_RETVAL_PARAM; - } - - rmid_cfg.map.num = num; - rmid_cfg.map.core = (unsigned *)malloc(sizeof(unsigned) * num); - rmid_cfg.map.rmid = - (pqos_rmid_t *)malloc(sizeof(pqos_rmid_t) * num); - - for (i = 0; i < num; i++) { - rmid_cfg.map.core[i] = cfg->rmid_cfg.map.core[i]; - rmid_cfg.map.rmid[i] = cfg->rmid_cfg.map.rmid[i]; - } - } -#endif pqos_mon_init_exit: - m_cpu = cpu; #ifdef __linux__ m_interface = cfg->interface; -#else - UNUSED_PARAM(cfg); #endif return ret; } @@ -212,1040 +125,122 @@ { int ret = PQOS_RETVAL_OK; - m_rmid_max = 0; #ifdef __linux__ if (m_interface == PQOS_INTER_OS || - m_interface == PQOS_INTER_OS_RESCTRL_MON) + m_interface == PQOS_INTER_OS_RESCTRL_MON) ret = os_mon_fini(); + if (m_interface == PQOS_INTER_MSR) + ret = hw_mon_fini(); +#else + ret = hw_mon_fini(); #endif -#ifdef PQOS_RMID_CUSTOM - if (rmid_cfg.map.core != NULL) - free(rmid_cfg.map.core); - if (rmid_cfg.map.rmid != NULL) - free(rmid_cfg.map.rmid); -#endif - - m_cpu = NULL; return ret; } -/* - * ======================================= - * ======================================= - * - * RMID allocation - * - * ======================================= - * ======================================= - */ - -/** - * @brief Gets max RMID number for given \a event - * - * @param [out] rmid resource monitoring id - * @param [in] event Monitoring event type - * - * @return Operations status - */ -static int -rmid_get_event_max(pqos_rmid_t *rmid, const enum pqos_mon_event event) +int +pqos_mon_poll_events(struct pqos_mon_data *group) { - pqos_rmid_t max_rmid = m_rmid_max; - const struct pqos_capability *item = NULL; - const struct pqos_cap_mon *mon = NULL; - unsigned mask_found = 0; unsigned i; - int ret; - - if (rmid == NULL) - return PQOS_RETVAL_PARAM; - - /** - * This is not so straight forward as it appears to be. - * We first have to figure out max RMID - * for given event type. In order to do so we need: - * - go through capabilities structure - * - find monitoring capability - * - look for the \a event in the event list - * - find max RMID matching the \a event - */ - ret = _pqos_cap_get_type(PQOS_CAP_TYPE_MON, &item); - if (ret != PQOS_RETVAL_OK) - return ret; - ASSERT(item != NULL); - mon = item->u.mon; - - /* Find which events are supported vs requested */ - max_rmid = m_rmid_max; - for (i = 0; i < mon->num_events; i++) - if (event & mon->events[i].type) { - mask_found |= mon->events[i].type; - max_rmid = (max_rmid > mon->events[i].max_rmid) ? - mon->events[i].max_rmid : max_rmid; - } - - /** - * Check if all of the events are supported - */ - if (event != mask_found || max_rmid == 0) - return PQOS_RETVAL_ERROR; - - ASSERT(m_rmid_max >= max_rmid); - - *rmid = max_rmid; - return PQOS_RETVAL_OK; -} - -/** - * @brief Get used RMIDs on ctx->cluster - * - * @param [inout] ctx poll context - * @param [in] event Monitoring event type - * - * @return Operations status - */ -static int -rmid_alloc(struct pqos_mon_poll_ctx *ctx, const enum pqos_mon_event event) -{ - const struct pqos_cpuinfo *cpu; int ret = PQOS_RETVAL_OK; - unsigned max_rmid = 0; - unsigned *core_list = NULL; - unsigned i, core_count; - pqos_rmid_t *rmid_list = NULL; - - ASSERT(ctx != NULL); - _pqos_cap_get(NULL, &cpu); - - /* Getting max RMID for given event */ - ret = rmid_get_event_max(&max_rmid, event); - if (ret != PQOS_RETVAL_OK) - return ret; - - /** - * Check for free RMID in the cluster by reading current associations. - */ - core_list = pqos_cpu_get_cores_l3id(cpu, ctx->cluster, &core_count); - if (core_list == NULL) - return PQOS_RETVAL_ERROR; - ASSERT(core_count > 0); - rmid_list = (pqos_rmid_t *)malloc(sizeof(rmid_list[0]) * core_count); - if (rmid_list == NULL) { - ret = PQOS_RETVAL_RESOURCE; - goto rmid_alloc_error; - } + /** List of non virtual events */ + const enum pqos_mon_event mon_event[] = { + PQOS_MON_EVENT_L3_OCCUP, + PQOS_MON_EVENT_LMEM_BW, + PQOS_MON_EVENT_TMEM_BW, + PQOS_PERF_EVENT_LLC_MISS, + (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES, + (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS}; - for (i = 0; i < core_count; i++) { - ret = mon_assoc_get(core_list[i], &rmid_list[i]); +#ifdef __linux__ + if (group->intl->resctrl.event != 0) { + ret = resctrl_lock_shared(); if (ret != PQOS_RETVAL_OK) - goto rmid_alloc_error; + return ret; } - - ret = PQOS_RETVAL_ERROR; - for (i = 1; i < max_rmid; i++) { - unsigned j = 0; - - for (j = 0; j < core_count; j++) - if (i == rmid_list[j]) - break; - if (j >= core_count) { - ret = PQOS_RETVAL_OK; - ctx->rmid = i; - break; - } - } - - rmid_alloc_error: - if (rmid_list != NULL) - free(rmid_list); - if (core_list != NULL) - free(core_list); - return ret; -} - -#ifdef PQOS_RMID_CUSTOM -/** - * @brief Gets RMID value based on information stored in rmid_cfg - * - * @param [inout] ctx poll context - * @param [in] event Monitoring event type - * @param [in] rmid_cfg rmid configuration parameters - * - * @return Operation status - * @retval PQOS_RETVAL_OK on success - */ -static int -rmid_alloc_custom(struct pqos_mon_poll_ctx *ctx, - const enum pqos_mon_event event, - const struct pqos_rmid_config *rmid_cfg) -{ - if (ctx == NULL) - return PQOS_RETVAL_PARAM; - - if (rmid_cfg == NULL || rmid_cfg->type == PQOS_RMID_TYPE_DEFAULT) { - return rmid_alloc(ctx, event); - } else if (rmid_cfg->type == PQOS_RMID_TYPE_MAP) { - unsigned i; - - for (i = 0; i < rmid_cfg->map.num; i++) { - if (ctx->lcore == rmid_cfg->map.core[i]) { - ctx->rmid = rmid_cfg->map.rmid[i]; - return PQOS_RETVAL_OK; - } - } - - LOG_ERROR("RMID Custom: No mapping for core %u\n", ctx->lcore); - } else { - LOG_ERROR("RMID Custom: Unsupported rmid type: %u\n", - rmid_cfg->type); - - return PQOS_RETVAL_PARAM; - } - - return PQOS_RETVAL_ERROR; -} #endif -/* - * ======================================= - * ======================================= - * - * Monitoring - * - * ======================================= - * ======================================= - */ - -/** - * @brief Scale event values to bytes - * - * Retrieve event scale factor and scale value to bytes - * - * @param event event scale factor to retrieve - * @param val value to be scaled - * - * @return scaled value - * @retval value in bytes - */ -static uint64_t -scale_event(const enum pqos_mon_event event, const uint64_t val) -{ - const struct pqos_cap *cap; - const struct pqos_monitor *pmon; - int ret; - - _pqos_cap_get(&cap, NULL); - - ret = pqos_cap_get_event(cap, event, &pmon); - ASSERT(ret == PQOS_RETVAL_OK); - if (ret != PQOS_RETVAL_OK) - return val; - else - return val * pmon->scale_factor; -} - -/** - * @brief Associates core with RMID at register level - * - * This function doesn't acquire API lock - * and can be used internally when lock is already taken. - * - * @param lcore logical core id - * @param rmid resource monitoring ID - * - * @return Operation status - * @retval PQOS_RETVAL_OK on success - */ -static int -mon_assoc_set(const unsigned lcore, - const pqos_rmid_t rmid) -{ - int ret = 0; - uint32_t reg = 0; - uint64_t val = 0; - - reg = PQOS_MSR_ASSOC; - ret = msr_read(lcore, reg, &val); - if (ret != MACHINE_RETVAL_OK) - return PQOS_RETVAL_ERROR; - - val &= PQOS_MSR_ASSOC_QECOS_MASK; - val |= (uint64_t)(rmid & PQOS_MSR_ASSOC_RMID_MASK); - - ret = msr_write(lcore, reg, val); - if (ret != MACHINE_RETVAL_OK) - return PQOS_RETVAL_ERROR; - - return PQOS_RETVAL_OK; -} - -/** - * @brief Reads \a lcore to RMID association - * - * @param lcore logical core id - * @param rmid place to store RMID \a lcore is assigned to - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - * @retval PQOS_RETVAL_ERROR on error - */ -static int -mon_assoc_get(const unsigned lcore, - pqos_rmid_t *rmid) -{ - int ret = 0; - uint32_t reg = PQOS_MSR_ASSOC; - uint64_t val = 0; - - ASSERT(rmid != NULL); - - ret = msr_read(lcore, reg, &val); - if (ret != MACHINE_RETVAL_OK) - return PQOS_RETVAL_ERROR; - - val &= PQOS_MSR_ASSOC_RMID_MASK; - *rmid = (pqos_rmid_t) val; - - return PQOS_RETVAL_OK; -} - -int -hw_mon_assoc_get(const unsigned lcore, - pqos_rmid_t *rmid) -{ - int ret = PQOS_RETVAL_OK; - - ret = _pqos_check_init(1); - if (ret != PQOS_RETVAL_OK) - goto pqos_mon_assoc_get__error; - - if (rmid == NULL) { - ret = PQOS_RETVAL_PARAM; - goto pqos_mon_assoc_get__error; - } - - ASSERT(m_cpu != NULL); - ret = pqos_cpu_check_core(m_cpu, lcore); - if (ret != PQOS_RETVAL_OK) { - ret = PQOS_RETVAL_PARAM; - goto pqos_mon_assoc_get__error; - } - - ret = mon_assoc_get(lcore, rmid); - - pqos_mon_assoc_get__error: - return ret; -} + for (i = 0; i < DIM(mon_event); i++) { + enum pqos_mon_event evt = mon_event[i]; -int hw_mon_reset(void) -{ - int ret = PQOS_RETVAL_OK; - unsigned i; - - ret = _pqos_check_init(1); - if (ret != PQOS_RETVAL_OK) - goto pqos_mon_reset_error; - - ASSERT(m_cpu != NULL); - for (i = 0; i < m_cpu->num_cores; i++) { - int retval = mon_assoc_set(m_cpu->cores[i].lcore, RMID0); - - if (retval != PQOS_RETVAL_OK) - ret = retval; - } - - pqos_mon_reset_error: - return ret; -} - -/** - * @brief Reads monitoring event data from given core - * - * This function doesn't acquire API lock. - * - * @param lcore logical core id - * @param rmid RMID to be read - * @param event monitoring event - * @param value place to store read value - * - * @return Operation status - * @retval PQOS_RETVAL_OK on success - */ -static int -mon_read(const unsigned lcore, - const pqos_rmid_t rmid, - const unsigned event, - uint64_t *value) -{ - int retries = 0, retval = PQOS_RETVAL_ERROR; - uint64_t val = 0; - uint64_t val_evtsel = 0; - int flag_wrt = 1; - - /** - * Set event selection register (RMID + event id) - */ - val_evtsel = ((uint64_t)rmid) & PQOS_MSR_MON_EVTSEL_RMID_MASK; - val_evtsel <<= PQOS_MSR_MON_EVTSEL_RMID_SHIFT; - val_evtsel |= ((uint64_t)event) & PQOS_MSR_MON_EVTSEL_EVTID_MASK; - - for (retries = 0; retries < 4; retries++) { - if (flag_wrt) { - if (msr_write(lcore, PQOS_MSR_MON_EVTSEL, - val_evtsel) != MACHINE_RETVAL_OK) - break; - } - if (msr_read(lcore, PQOS_MSR_MON_QMC, - &val) != MACHINE_RETVAL_OK) - break; - if ((val & PQOS_MSR_MON_QMC_ERROR) != 0ULL) { - /* Read back IA32_QM_EVTSEL register - * to check for content change. - */ - if (msr_read(lcore, PQOS_MSR_MON_EVTSEL, - &val) != MACHINE_RETVAL_OK) - break; - if (val != val_evtsel) { - flag_wrt = 1; - continue; - } - } - if ((val & PQOS_MSR_MON_QMC_UNAVAILABLE) != 0ULL) { - /** - * Waiting for monitoring data - */ - flag_wrt = 0; - continue; - } - retval = PQOS_RETVAL_OK; - break; - } - /** - * Store event value - */ - if (retval == PQOS_RETVAL_OK) - *value = (val & PQOS_MSR_MON_QMC_DATA_MASK); - else - LOG_WARN("Error reading event %u on core %u (RMID%u)!\n", - event, lcore, (unsigned) rmid); - - return retval; -} - -/** - * @brief Reads monitoring event data from given core - * - * @param p pointer to monitoring structure - * - * @return Operation status - * @retval PQOS_RETVAL_OK on success - */ -static int -pqos_core_poll(struct pqos_mon_data *p) -{ - struct pqos_event_values *pv = &p->values; - int retval = PQOS_RETVAL_OK; - unsigned i; - - if (p->event & PQOS_MON_EVENT_L3_OCCUP) { - uint64_t total = 0; - - for (i = 0; i < p->num_poll_ctx; i++) { - uint64_t tmp = 0; - int ret; - - ret = mon_read(p->poll_ctx[i].lcore, - p->poll_ctx[i].rmid, - get_event_id(PQOS_MON_EVENT_L3_OCCUP), - &tmp); - if (ret != PQOS_RETVAL_OK) { - retval = PQOS_RETVAL_ERROR; - goto pqos_core_poll__exit; - } - total += tmp; - } - pv->llc = scale_event(PQOS_MON_EVENT_L3_OCCUP, total); - } - if (p->event & (PQOS_MON_EVENT_LMEM_BW | PQOS_MON_EVENT_RMEM_BW)) { - uint64_t total = 0, old_value = pv->mbm_local; - - for (i = 0; i < p->num_poll_ctx; i++) { - uint64_t tmp = 0; - int ret; - - ret = mon_read(p->poll_ctx[i].lcore, - p->poll_ctx[i].rmid, - get_event_id(PQOS_MON_EVENT_LMEM_BW), - &tmp); - if (ret != PQOS_RETVAL_OK) { - retval = PQOS_RETVAL_ERROR; - goto pqos_core_poll__exit; - } - total += tmp; - } - pv->mbm_local = total; - pv->mbm_local_delta = get_delta(old_value, pv->mbm_local); - pv->mbm_local_delta = scale_event(PQOS_MON_EVENT_LMEM_BW, - pv->mbm_local_delta); - } - if (p->event & (PQOS_MON_EVENT_TMEM_BW | PQOS_MON_EVENT_RMEM_BW)) { - uint64_t total = 0, old_value = pv->mbm_total; - - for (i = 0; i < p->num_poll_ctx; i++) { - uint64_t tmp = 0; - int ret; - - ret = mon_read(p->poll_ctx[i].lcore, - p->poll_ctx[i].rmid, - get_event_id(PQOS_MON_EVENT_TMEM_BW), - &tmp); - if (ret != PQOS_RETVAL_OK) { - retval = PQOS_RETVAL_ERROR; - goto pqos_core_poll__exit; - } - total += tmp; - } - pv->mbm_total = total; - pv->mbm_total_delta = get_delta(old_value, pv->mbm_total); - pv->mbm_total_delta = scale_event(PQOS_MON_EVENT_TMEM_BW, - pv->mbm_total_delta); - } - if (p->event & PQOS_MON_EVENT_RMEM_BW) { - pv->mbm_remote = 0; - if (pv->mbm_total > pv->mbm_local) - pv->mbm_remote = pv->mbm_total - pv->mbm_local; - pv->mbm_remote_delta = 0; - if (pv->mbm_total_delta > pv->mbm_local_delta) - pv->mbm_remote_delta = - pv->mbm_total_delta - pv->mbm_local_delta; - } - if (p->event & PQOS_PERF_EVENT_IPC) { /** - * If multiple cores monitored in one group - * then we have to accumulate the values in the group. + * poll hw event */ - uint64_t unhalted = 0, retired = 0; - unsigned n; - - for (n = 0; n < p->num_cores; n++) { - uint64_t tmp = 0; - int ret = msr_read(p->cores[n], - IA32_MSR_INST_RETIRED_ANY, &tmp); - if (ret != MACHINE_RETVAL_OK) { - retval = PQOS_RETVAL_ERROR; - goto pqos_core_poll__exit; - } - retired += tmp; - - ret = msr_read(p->cores[n], - IA32_MSR_CPU_UNHALTED_THREAD, &tmp); - if (ret != MACHINE_RETVAL_OK) { - retval = PQOS_RETVAL_ERROR; - goto pqos_core_poll__exit; - } - unhalted += tmp; + if (group->intl->hw.event & evt) { + ret = hw_mon_poll(group, evt); + if (ret != PQOS_RETVAL_OK) + goto poll_events_exit; } - pv->ipc_unhalted_delta = unhalted - pv->ipc_unhalted; - pv->ipc_retired_delta = retired - pv->ipc_retired; - pv->ipc_unhalted = unhalted; - pv->ipc_retired = retired; - if (pv->ipc_unhalted_delta == 0) - pv->ipc = 0.0; - else - pv->ipc = (double) pv->ipc_retired_delta / - (double) pv->ipc_unhalted_delta; - } - if (p->event & PQOS_PERF_EVENT_LLC_MISS) { +#ifdef __linux__ /** - * If multiple cores monitored in one group - * then we have to accumulate the values in the group. + * poll perf event */ - uint64_t missed = 0; - unsigned n; - - for (n = 0; n < p->num_cores; n++) { - uint64_t tmp = 0; - int ret = msr_read(p->cores[n], - IA32_MSR_PMC0, &tmp); - if (ret != MACHINE_RETVAL_OK) { - retval = PQOS_RETVAL_ERROR; - goto pqos_core_poll__exit; - } - missed += tmp; - } - - pv->llc_misses_delta = missed - pv->llc_misses; - pv->llc_misses = missed; - } - if (!p->valid_mbm_read) { - /* Report zero memory bandwidth with first read */ - pv->mbm_remote_delta = 0; - pv->mbm_local_delta = 0; - pv->mbm_total_delta = 0; - p->valid_mbm_read = 1; - } - pqos_core_poll__exit: - return retval; -} - -/** - * @brief Sets up IA32 performance counters for IPC and LLC miss ratio events - * - * @param num_cores number of cores in \a cores table - * @param cores table with core id's - * @param event mask of selected monitoring events - * - * @return Operation status - * @retval PQOS_RETVAL_OK on success - */ -static int -ia32_perf_counter_start(const unsigned num_cores, - const unsigned *cores, - const enum pqos_mon_event event) -{ - uint64_t global_ctrl_mask = 0; - unsigned i; - - ASSERT(cores != NULL && num_cores > 0); - - if (!(event & (PQOS_PERF_EVENT_LLC_MISS | PQOS_PERF_EVENT_IPC))) - return PQOS_RETVAL_OK; - - if (event & PQOS_PERF_EVENT_IPC) - global_ctrl_mask |= (0x3ULL << 32); /**< fixed counters 0&1 */ - - if (event & PQOS_PERF_EVENT_LLC_MISS) - global_ctrl_mask |= 0x1ULL; /**< programmable counter 0 */ - - /** - * Fixed counters are used for IPC calculations. - * Programmable counters are used for LLC miss calculations. - * Let's check if they are in use. - */ - for (i = 0; i < num_cores; i++) { - uint64_t global_inuse = 0; - int ret; - - ret = msr_read(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, - &global_inuse); - if (ret != MACHINE_RETVAL_OK) - return PQOS_RETVAL_ERROR; - if (global_inuse & global_ctrl_mask) - LOG_WARN("Hijacking performance counters on core %u\n", - cores[i]); - } - - /** - * - Disable counters in global control and - * reset counter values to 0. - * - Program counters for desired events - * - Enable counters in global control - */ - for (i = 0; i < num_cores; i++) { - const uint64_t fixed_ctrl = 0x33ULL; /**< track usr + os */ - int ret; - - ret = msr_write(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, 0); - if (ret != MACHINE_RETVAL_OK) - break; - - if (event & PQOS_PERF_EVENT_IPC) { - ret = msr_write(cores[i], IA32_MSR_INST_RETIRED_ANY, 0); - if (ret != MACHINE_RETVAL_OK) - break; - ret = msr_write(cores[i], - IA32_MSR_CPU_UNHALTED_THREAD, 0); - if (ret != MACHINE_RETVAL_OK) - break; - ret = msr_write(cores[i], - IA32_MSR_FIXED_CTR_CTRL, fixed_ctrl); - if (ret != MACHINE_RETVAL_OK) - break; - } - - if (event & PQOS_PERF_EVENT_LLC_MISS) { - const uint64_t evtsel0_miss = IA32_EVENT_LLC_MISS_MASK | - (IA32_EVENT_LLC_MISS_UMASK << 8) | - (1ULL << 16) | (1ULL << 17) | (1ULL << 22); - - ret = msr_write(cores[i], IA32_MSR_PMC0, 0); - if (ret != MACHINE_RETVAL_OK) - break; - ret = msr_write(cores[i], IA32_MSR_PERFEVTSEL0, - evtsel0_miss); - if (ret != MACHINE_RETVAL_OK) - break; - } - - ret = msr_write(cores[i], - IA32_MSR_PERF_GLOBAL_CTRL, global_ctrl_mask); - if (ret != MACHINE_RETVAL_OK) - break; - } - - if (i < num_cores) - return PQOS_RETVAL_ERROR; - - return PQOS_RETVAL_OK; -} - -/** - * @brief Disables IA32 performance counters - * - * @param num_cores number of cores in \a cores table - * @param cores table with core id's - * @param event mask of selected monitoring events - * - * @return Operation status - * @retval PQOS_RETVAL_OK on success - */ -static int -ia32_perf_counter_stop(const unsigned num_cores, - const unsigned *cores, - const enum pqos_mon_event event) -{ - int retval = PQOS_RETVAL_OK; - unsigned i; - - ASSERT(cores != NULL && num_cores > 0); - - if (!(event & (PQOS_PERF_EVENT_LLC_MISS | PQOS_PERF_EVENT_IPC))) - return retval; - - for (i = 0; i < num_cores; i++) { - int ret = msr_write(cores[i], IA32_MSR_PERF_GLOBAL_CTRL, 0); - - if (ret != MACHINE_RETVAL_OK) - retval = PQOS_RETVAL_ERROR; - } - return retval; -} - -int -hw_mon_start(const unsigned num_cores, - const unsigned *cores, - const enum pqos_mon_event event, - void *context, - struct pqos_mon_data *group) -{ - unsigned core2cluster[num_cores]; - struct pqos_mon_poll_ctx ctxs[num_cores]; - unsigned num_ctxs = 0; - unsigned i = 0; - int ret = PQOS_RETVAL_OK; - int retval = PQOS_RETVAL_OK; - const struct pqos_cap *cap; - - ASSERT(group != NULL); - ASSERT(cores != NULL); - ASSERT(num_cores > 0); - ASSERT(event > 0); - ASSERT(m_cpu != NULL); - - memset(ctxs, 0, sizeof(ctxs)); - - _pqos_cap_get(&cap, NULL); - - /** - * Validate if event is listed in capabilities - */ - for (i = 0; i < (sizeof(event) * 8); i++) { - const enum pqos_mon_event evt_mask = - (enum pqos_mon_event)(1U << i); - const struct pqos_monitor *ptr = NULL; - - if (!(evt_mask & event)) - continue; - - ret = pqos_cap_get_event(cap, evt_mask, &ptr); - if (ret != PQOS_RETVAL_OK || ptr == NULL) - return PQOS_RETVAL_PARAM; - } - - /** - * Check if all requested cores are valid - * and not used by other monitoring processes. - * - * Check if any of requested cores is already subject to monitoring - * within this process. - * - * Initialize poll context table: - * - get core cluster - * - allocate RMID - */ - for (i = 0; i < num_cores; i++) { - const unsigned lcore = cores[i]; - unsigned j, cluster = 0; - pqos_rmid_t rmid = RMID0; - - ret = pqos_cpu_check_core(m_cpu, lcore); - if (ret != PQOS_RETVAL_OK) { - retval = PQOS_RETVAL_PARAM; - goto pqos_mon_start_error1; + if (group->intl->perf.event & evt) { + ret = perf_mon_poll(group, evt); + if (ret != PQOS_RETVAL_OK) + goto poll_events_exit; } - ret = mon_assoc_get(lcore, &rmid); - if (ret != PQOS_RETVAL_OK) { - retval = PQOS_RETVAL_PARAM; - goto pqos_mon_start_error1; - } - - if (rmid != RMID0) { - /* If not RMID0 then it is already monitored */ - LOG_INFO("Core %u is already monitored with " - "RMID%u.\n", lcore, rmid); - retval = PQOS_RETVAL_RESOURCE; - goto pqos_mon_start_error1; - } - - ret = pqos_cpu_get_clusterid(m_cpu, lcore, &cluster); - if (ret != PQOS_RETVAL_OK) { - retval = PQOS_RETVAL_PARAM; - goto pqos_mon_start_error1; + /** + * poll resctrl event + */ + if (group->intl->resctrl.event & evt) { + ret = resctrl_mon_poll(group, evt); + if (ret != PQOS_RETVAL_OK) + goto poll_events_exit; } - core2cluster[i] = cluster; - - for (j = 0; j < num_ctxs; j++) - if (ctxs[j].lcore == lcore || - ctxs[j].cluster == cluster) - break; - - if (j >= num_ctxs) { - enum pqos_mon_event ctx_event = - (enum pqos_mon_event)(event & - (~(PQOS_PERF_EVENT_IPC | - PQOS_PERF_EVENT_LLC_MISS))); - - /** - * New cluster is found - * - save cluster id in the table - * - allocate RMID for the cluster - */ - ctxs[num_ctxs].lcore = lcore; - ctxs[num_ctxs].cluster = cluster; -#ifdef PQOS_RMID_CUSTOM - ret = rmid_alloc_custom(&ctxs[num_ctxs], ctx_event, - &rmid_cfg); -#else - ret = rmid_alloc(&ctxs[num_ctxs], ctx_event); #endif - if (ret != PQOS_RETVAL_OK) { - retval = ret; - goto pqos_mon_start_error1; - } - - num_ctxs++; - } } /** - * Fill in the monitoring group structure + * Calculate values of virtual events */ - memset(group, 0, sizeof(*group)); - group->cores = (unsigned *) malloc(sizeof(group->cores[0]) * num_cores); - if (group->cores == NULL) { - retval = PQOS_RETVAL_RESOURCE; - goto pqos_mon_start_error1; - } + if (group->event & PQOS_MON_EVENT_RMEM_BW) { + const struct pqos_cap *cap; + const struct pqos_monitor *pmon; + uint64_t max_value = 0; - group->poll_ctx = (struct pqos_mon_poll_ctx *) - malloc(sizeof(group->poll_ctx[0]) * num_ctxs); - if (group->poll_ctx == NULL) { - retval = PQOS_RETVAL_RESOURCE; - goto pqos_mon_start_error2; - } + group->values.mbm_remote_delta = 0; + if (group->values.mbm_total_delta > + group->values.mbm_local_delta) + group->values.mbm_remote_delta = + group->values.mbm_total_delta - + group->values.mbm_local_delta; - ret = ia32_perf_counter_start(num_cores, cores, event); - if (ret != PQOS_RETVAL_OK) { - retval = ret; - goto pqos_mon_start_error2; - } + _pqos_cap_get(&cap, NULL); - /** - * Associate requested cores with - * the allocated RMID - */ - group->num_cores = num_cores; - for (i = 0; i < num_cores; i++) { - unsigned cluster, j; - pqos_rmid_t rmid; - - cluster = core2cluster[i]; - for (j = 0; j < num_ctxs; j++) - if (ctxs[j].cluster == cluster) - break; - if (j >= num_ctxs) { - retval = PQOS_RETVAL_ERROR; - goto pqos_mon_start_error2; - } - rmid = ctxs[j].rmid; + ret = pqos_cap_get_event(cap, PQOS_MON_EVENT_RMEM_BW, &pmon); + if (ret == PQOS_RETVAL_OK) + max_value = 1LLU << pmon->counter_length; - group->cores[i] = cores[i]; - ret = mon_assoc_set(cores[i], rmid); - if (ret != PQOS_RETVAL_OK) { - retval = ret; - goto pqos_mon_start_error2; - } - } - - group->num_poll_ctx = num_ctxs; - for (i = 0; i < num_ctxs; i++) - group->poll_ctx[i] = ctxs[i]; - - group->event = event; - group->context = context; - - pqos_mon_start_error2: - if (retval != PQOS_RETVAL_OK) { - for (i = 0; i < num_cores; i++) - (void) mon_assoc_set(cores[i], RMID0); - - if (group->poll_ctx != NULL) - free(group->poll_ctx); - - if (group->cores != NULL) - free(group->cores); - } - pqos_mon_start_error1: - - return retval; -} - -int -hw_mon_stop(struct pqos_mon_data *group) -{ - int ret = PQOS_RETVAL_OK; - int retval = PQOS_RETVAL_OK; - unsigned i = 0; - - ASSERT(group != NULL); - - if (group->num_cores == 0 || group->cores == NULL || - group->num_poll_ctx == 0 || group->poll_ctx == NULL) { - return PQOS_RETVAL_PARAM; - } - - ASSERT(m_cpu != NULL); - for (i = 0; i < group->num_poll_ctx; i++) { - /** - * Validate core list in the group structure is correct - */ - const unsigned lcore = group->poll_ctx[i].lcore; - pqos_rmid_t rmid = RMID0; - - ret = pqos_cpu_check_core(m_cpu, lcore); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_PARAM; - ret = mon_assoc_get(lcore, &rmid); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_PARAM; - if (rmid != group->poll_ctx[i].rmid) - LOG_WARN("Core %u RMID association changed from %u " - "to %u! The core has been hijacked!\n", - lcore, group->poll_ctx[i].rmid, rmid); + if (max_value > 0 && + group->values.mbm_local > group->values.mbm_total) + group->values.mbm_remote = max_value - + group->values.mbm_local + + group->values.mbm_total; + else + group->values.mbm_remote = + group->values.mbm_total - group->values.mbm_local; } - - for (i = 0; i < group->num_cores; i++) { - /** - * Associate cores from the group back with RMID0 - */ - ret = mon_assoc_set(group->cores[i], RMID0); - if (ret != PQOS_RETVAL_OK) - retval = PQOS_RETVAL_RESOURCE; + if (group->event & PQOS_PERF_EVENT_IPC) { + if (group->values.ipc_unhalted_delta > 0) + group->values.ipc = + (double)group->values.ipc_retired_delta / + (double)group->values.ipc_unhalted_delta; + else + group->values.ipc = 0; } - /** - * Stop IA32 performance counters - */ - ret = ia32_perf_counter_stop(group->num_cores, group->cores, - group->event); - if (ret != PQOS_RETVAL_OK) - retval = PQOS_RETVAL_RESOURCE; - - /** - * Free poll contexts, core list and clear the group structure - */ - free(group->cores); - free(group->poll_ctx); - memset(group, 0, sizeof(*group)); - - return retval; -} - -int -hw_mon_poll(struct pqos_mon_data **groups, - const unsigned num_groups) -{ - unsigned i = 0; - - ASSERT(groups != NULL); - ASSERT(num_groups > 0); - - for (i = 0; i < num_groups; i++) { - int ret = pqos_core_poll(groups[i]); + if (ret == PQOS_RETVAL_OK) + group->intl->valid_mbm_read = 1; - if (ret != PQOS_RETVAL_OK) - LOG_WARN("Failed to read event on " - "core %u\n", groups[i]->cores[0]); - } - return PQOS_RETVAL_OK; -} -/* - * ======================================= - * ======================================= - * - * Small utils - * - * ======================================= - * ======================================= - */ - -/** - * @brief Maps PQoS API event onto an MSR event id - * - * @param [in] event PQoS API event id - * - * @return MSR event id - * @retval 0 if not successful - */ -static unsigned -get_event_id(const enum pqos_mon_event event) -{ - switch (event) { - case PQOS_MON_EVENT_L3_OCCUP: - return 1; - break; - case PQOS_MON_EVENT_LMEM_BW: - return 3; - break; - case PQOS_MON_EVENT_TMEM_BW: - return 2; - break; - case PQOS_MON_EVENT_RMEM_BW: - default: - ASSERT(0); /**< this means bug */ - break; - } - return 0; -} +poll_events_exit: +#ifdef __linux__ + if (group->intl->resctrl.event != 0) + resctrl_lock_release(); +#endif -/** - * @brief Gives the difference between two values with regard to the possible - * overrun - * - * @param old_value previous value - * @param new_value current value - * @return difference between the two values - */ -static uint64_t -get_delta(const uint64_t old_value, const uint64_t new_value) -{ - if (old_value > new_value) - return (MBM_MAX_VALUE - old_value) + new_value; - else - return new_value - old_value; + return ret; } - diff -Nru intel-cmt-cat-3.2/lib/monitoring.h intel-cmt-cat-4.0/lib/monitoring.h --- intel-cmt-cat-3.2/lib/monitoring.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/monitoring.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,29 +43,71 @@ extern "C" { #endif -/** - * @brief Initializes monitoring sub-module of the library (CMT) - * - * @param cpu cpu topology structure - * @param cap capabilities structure - * @param cfg library configuration structure - * - * @return Operation status - * @retval PQOS_RETVAL_OK success - */ -int pqos_mon_init(const struct pqos_cpuinfo *cpu, - const struct pqos_cap *cap, - const struct pqos_config *cfg); +#include "pqos.h" /** - * @brief Shuts down monitoring sub-module of the library - * - * @return Operation status + * Core monitoring poll context */ -int pqos_mon_fini(void); +struct pqos_mon_poll_ctx { + unsigned lcore; + unsigned cluster; + pqos_rmid_t rmid; +}; + +/** + * Perf monitoring poll context + */ +struct pqos_mon_perf_ctx { + int fd_llc; + int fd_mbl; + int fd_mbt; + int fd_inst; + int fd_cyc; + int fd_llc_misses; +}; + +/** + * Internal monitoring group data structure + */ +struct pqos_mon_data_internal { + /** + * Perf specific section + */ + struct { + enum pqos_mon_event event; /**< Started perf events */ + struct pqos_mon_perf_ctx *ctx; /**< Perf poll context for each + core/tid */ + } perf; + + /** + * Resctrl specific section + */ + struct { + enum pqos_mon_event event; /**< Started resctrl events */ + char *mon_group; + struct pqos_event_values values_storage; /**< stores values + of monitoring group + that was moved to + another COS */ + unsigned *l3id; /**< list of l3ids being monitored */ + unsigned num_l3id; /**< Number of l3ids */ + + } resctrl; + + /** + * Hw specific section + */ + struct { + enum pqos_mon_event event; /**< Started hw events */ + struct pqos_mon_poll_ctx *ctx; /**< core, cluster & RMID */ + unsigned num_ctx; /**< number of poll contexts */ + } hw; + + int valid_mbm_read; /**< flag to discard 1st invalid read */ +}; /** - * @brief Initializes hardware monitoring sub-module of the library (CMT) + * @brief Initializes monitoring sub-module of the library (CMT) * * @param cpu cpu topology structure * @param cap capabilities structure @@ -74,115 +116,26 @@ * @return Operation status * @retval PQOS_RETVAL_OK success */ -int hw_mon_init(const struct pqos_cpuinfo *cpu, +int pqos_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap, const struct pqos_config *cfg); /** - * @brief Shuts down hardware monitoring sub-module of the library + * @brief Shuts down monitoring sub-module of the library * * @return Operation status */ -int hw_mon_fini(void); - -/** - * @brief Hardware interface to reset monitoring by binding all cores with RMID0 - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -int hw_mon_reset(void); - -/** - * @brief Hardware interface to read RMID association of the \a lcore - * - * @param [in] lcore CPU logical core id - * @param [out] rmid place to store resource monitoring id - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -int hw_mon_assoc_get(const unsigned lcore, - pqos_rmid_t *rmid); - -/** - * @brief Hardware interface to start resource monitoring on selected - * group of cores - * - * The function sets up content of the \a group structure. - * - * Note that \a event cannot select PQOS_PERF_EVENT_IPC or - * PQOS_PERF_EVENT_L3_MISS events without any PQoS event - * selected at the same time. - * - * @param [in] num_cores number of cores in \a cores array - * @param [in] cores array of logical core id's - * @param [in] event combination of monitoring events - * @param [in] context a pointer for application's convenience - * (unused by the library) - * @param [in,out] group a pointer to monitoring structure - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -int hw_mon_start(const unsigned num_cores, - const unsigned *cores, - const enum pqos_mon_event event, - void *context, - struct pqos_mon_data *group); - -/** - * @brief Hardware interface to stop resource monitoring data for selected - * monitoring group - * - * @param [in] group monitoring context for selected number of cores - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -int hw_mon_stop(struct pqos_mon_data *group); - -/** - * @brief Hardware interface poll monitoring data from requested cores - * - * @param [in] groups table of monitoring group pointers to be be updated - * @param [in] num_groups number of monitoring groups in the table - * - * @return Operations status - * @retval PQOS_RETVAL_OK on success - */ -int hw_mon_poll(struct pqos_mon_data **groups, - const unsigned num_groups); - -/* - * ======================================= - * Allocation Technology - * ======================================= - */ - -/** - * @brief Hardware interface to associate \a lcore with given class of service - * - * @param [in] lcore CPU logical core id - * @param [in] class_id class of service - * - * @return Operations status - */ -int hw_alloc_assoc_set(const unsigned lcore, - const unsigned class_id); +int pqos_mon_fini(void); /** - * @brief Hardware interface to read association of \a lcore with - * class of service + * @brief Poll monitoring data from requested groups * - * @param [in] lcore CPU logical core id - * @param [out] class_id class of service + * @param group monitoring group pointer to be be updated * * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int hw_alloc_assoc_get(const unsigned lcore, - unsigned *class_id); +int pqos_mon_poll_events(struct pqos_mon_data *group); #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/lib/os_allocation.c intel-cmt-cat-4.0/lib/os_allocation.c --- intel-cmt-cat-3.2/lib/os_allocation.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/os_allocation.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,7 +39,7 @@ #include #include #include -#include /**< scandir() */ +#include /**< scandir() */ #include "pqos.h" #include "os_allocation.h" @@ -90,54 +90,51 @@ return PQOS_RETVAL_PARAM; } - if (mba_cfg != PQOS_MBA_DEFAULT && - mba_cfg != PQOS_MBA_CTRL) { + if (mba_cfg != PQOS_MBA_DEFAULT && mba_cfg != PQOS_MBA_CTRL) { LOG_ERROR("Invalid MBA mounting setting %d!\n", mba_cfg); return PQOS_RETVAL_PARAM; } if (l3_cdp_cfg == PQOS_REQUIRE_CDP_OFF && - l2_cdp_cfg == PQOS_REQUIRE_CDP_OFF && - mba_cfg == PQOS_MBA_DEFAULT) + l2_cdp_cfg == PQOS_REQUIRE_CDP_OFF && mba_cfg == PQOS_MBA_DEFAULT) goto mount; /* Get L3 CAT capabilities */ - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &alloc_cap); if (alloc_cap != NULL) l3_cap = alloc_cap->u.l3ca; /* Get L2 CAT capabilities */ - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &alloc_cap); if (alloc_cap != NULL) l2_cap = alloc_cap->u.l2ca; /* Get MBA capabilities */ - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &alloc_cap); if (alloc_cap != NULL) mba_cap = alloc_cap->u.mba; if (l3_cap != NULL && !l3_cap->cdp && - l3_cdp_cfg == PQOS_REQUIRE_CDP_ON) { + l3_cdp_cfg == PQOS_REQUIRE_CDP_ON) { /* Check against erroneous CDP request */ LOG_ERROR("L3 CDP requested but not supported by the " "platform!\n"); return PQOS_RETVAL_PARAM; } if (l2_cap != NULL && !l2_cap->cdp && - l2_cdp_cfg == PQOS_REQUIRE_CDP_ON) { + l2_cdp_cfg == PQOS_REQUIRE_CDP_ON) { /* Check against erroneous CDP request */ LOG_ERROR("L2 CDP requested but not supported by the " "platform!\n"); return PQOS_RETVAL_PARAM; } - if (mba_cap != NULL && mba_cap->ctrl == 0 && - mba_cfg == PQOS_MBA_CTRL) { + if (mba_cap != NULL && mba_cap->ctrl == 0 && mba_cfg == PQOS_MBA_CTRL) { /* Check against erroneous MBA request */ LOG_ERROR("MBA CTRL requested but not supported!\n"); return PQOS_RETVAL_PARAM; } - mount: +mount: return resctrl_mount(l3_cdp_cfg, l2_cdp_cfg, mba_cfg); } @@ -155,9 +152,9 @@ const struct pqos_capability *l2_cap; const struct pqos_capability *mba_cap; - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &l3_cap); - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &l2_cap); - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &mba_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &l3_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &l2_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &mba_cap); /** * Check if resctrl is supported @@ -168,7 +165,7 @@ /** * Check if resctrl is mounted */ - if (access(RESCTRL_PATH"/cpus", F_OK) != 0) { + if (access(RESCTRL_PATH "/cpus", F_OK) != 0) { enum pqos_cdp_config l3_cdp_mount = PQOS_REQUIRE_CDP_OFF; enum pqos_cdp_config l2_cdp_mount = PQOS_REQUIRE_CDP_OFF; enum pqos_mba_config mba_mount = PQOS_MBA_DEFAULT; @@ -212,45 +209,45 @@ _pqos_cap_get(&cap, NULL); ret = resctrl_alloc_get_grps_num(cap, &num_grps); - if (ret != PQOS_RETVAL_OK) - return ret; + if (ret != PQOS_RETVAL_OK) + return ret; /* * Detect/Create all available COS resctrl groups */ - for (i = 1; i < num_grps; i++) { - char buf[128]; - struct stat st; - - memset(buf, 0, sizeof(buf)); - if (snprintf(buf, sizeof(buf) - 1, - "%s/COS%d", RESCTRL_PATH, (int) i) < 0) - return PQOS_RETVAL_ERROR; - - /* if resctrl group doesn't exist - create it */ - if (stat(buf, &st) == 0) { - LOG_DEBUG("resctrl group COS%d detected\n", i); - continue; - } - - if (mkdir(buf, 0755) == -1) { - LOG_DEBUG("Failed to create resctrl group %s!\n", buf); - return PQOS_RETVAL_BUSY; - } - LOG_DEBUG("resctrl group COS%d created\n", i); - } + for (i = 1; i < num_grps; i++) { + char buf[128]; + struct stat st; + + memset(buf, 0, sizeof(buf)); + if (snprintf(buf, sizeof(buf) - 1, "%s/COS%d", RESCTRL_PATH, + (int)i) < 0) + return PQOS_RETVAL_ERROR; + + /* if resctrl group doesn't exist - create it */ + if (stat(buf, &st) == 0) { + LOG_DEBUG("resctrl group COS%d detected\n", i); + continue; + } + + if (mkdir(buf, 0755) == -1) { + LOG_DEBUG("Failed to create resctrl group %s!\n", buf); + return PQOS_RETVAL_BUSY; + } + LOG_DEBUG("resctrl group COS%d created\n", i); + } - return PQOS_RETVAL_OK; + return PQOS_RETVAL_OK; } int os_alloc_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap) { - int ret; + int ret; if (cpu == NULL || cap == NULL) - return PQOS_RETVAL_PARAM; + return PQOS_RETVAL_PARAM; - m_cpu = cpu; + m_cpu = cpu; ret = os_alloc_check(); if (ret != PQOS_RETVAL_OK) @@ -277,8 +274,8 @@ int os_alloc_assoc_set(const unsigned lcore, const unsigned class_id) { - int ret; - unsigned grps; + int ret; + unsigned grps; int ret_mon; char mon_group[256]; const struct pqos_cap *cap; @@ -294,9 +291,9 @@ if (ret != PQOS_RETVAL_OK) return ret; - if (class_id >= grps) - /* class_id is out of bounds */ - return PQOS_RETVAL_PARAM; + if (class_id >= grps) + /* class_id is out of bounds */ + return PQOS_RETVAL_PARAM; ret = resctrl_lock_exclusive(); if (ret != PQOS_RETVAL_OK) @@ -309,7 +306,8 @@ ret_mon = resctrl_mon_assoc_get(lcore, mon_group, sizeof(mon_group)); if (ret_mon != PQOS_RETVAL_OK && ret_mon != PQOS_RETVAL_RESOURCE) LOG_WARN("Failed to obtain monitoring group assignment for " - "core %u\n", lcore); + "core %u\n", + lcore); ret = resctrl_alloc_assoc_set(lcore, class_id); if (ret != PQOS_RETVAL_OK) @@ -320,13 +318,14 @@ ret_mon = resctrl_mon_assoc_set(lcore, mon_group); if (ret_mon != PQOS_RETVAL_OK) LOG_WARN("Could not assign core %d back to monitoring " - "group\n", lcore); + "group\n", + lcore); } - os_alloc_assoc_set_exit: +os_alloc_assoc_set_exit: resctrl_lock_release(); - return ret; + return ret; } int @@ -338,8 +337,8 @@ ASSERT(m_cpu != NULL); ret = pqos_cpu_check_core(m_cpu, lcore); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_PARAM; + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_PARAM; ret = resctrl_lock_shared(); if (ret != PQOS_RETVAL_OK) @@ -349,7 +348,7 @@ resctrl_lock_release(); - return ret; + return ret; } unsigned * @@ -365,18 +364,18 @@ _pqos_cap_get(&cap, NULL); ret = resctrl_alloc_get_grps_num(cap, &grps); - if (ret != PQOS_RETVAL_OK) - return NULL; + if (ret != PQOS_RETVAL_OK) + return NULL; - if (class_id >= grps) - /* class_id is out of bounds */ - return NULL; + if (class_id >= grps) + /* class_id is out of bounds */ + return NULL; ret = resctrl_lock_shared(); if (ret != PQOS_RETVAL_OK) return NULL; - tasks = resctrl_alloc_task_read(class_id, count); + tasks = resctrl_alloc_task_read(class_id, count); resctrl_lock_release(); @@ -430,7 +429,7 @@ unsigned i, cos0 = 0; struct resctrl_cpumask mask; - ASSERT(m_cpu != NULL); + ASSERT(m_cpu != NULL); ASSERT(core_num > 0 && core_array != NULL); ret = resctrl_lock_exclusive(); @@ -444,18 +443,18 @@ if (ret != PQOS_RETVAL_OK) goto os_alloc_release_unlock; for (i = 0; i < core_num; i++) { - if (core_array[i] >= m_cpu->num_cores) { - ret = PQOS_RETVAL_ERROR; + if (core_array[i] >= m_cpu->num_cores) { + ret = PQOS_RETVAL_ERROR; goto os_alloc_release_unlock; } resctrl_cpumask_set(core_array[i], &mask); - } + } ret = resctrl_alloc_cpumask_write(cos0, &mask); if (ret != PQOS_RETVAL_OK) LOG_ERROR("CPU assoc reset failed\n"); - os_alloc_release_unlock: +os_alloc_release_unlock: resctrl_lock_release(); return ret; @@ -469,25 +468,25 @@ static int os_alloc_reset_cores(void) { - const unsigned default_cos = 0; - struct resctrl_cpumask mask; - unsigned i; - int ret; + const unsigned default_cos = 0; + struct resctrl_cpumask mask; + unsigned i; + int ret; - LOG_INFO("OS alloc reset - core assoc\n"); + LOG_INFO("OS alloc reset - core assoc\n"); - ret = resctrl_alloc_cpumask_read(default_cos, &mask); - if (ret != PQOS_RETVAL_OK) - return ret; + ret = resctrl_alloc_cpumask_read(default_cos, &mask); + if (ret != PQOS_RETVAL_OK) + return ret; - for (i = 0; i < m_cpu->num_cores; i++) - resctrl_cpumask_set(m_cpu->cores[i].lcore, &mask); + for (i = 0; i < m_cpu->num_cores; i++) + resctrl_cpumask_set(m_cpu->cores[i].lcore, &mask); - ret = resctrl_alloc_cpumask_write(default_cos, &mask); - if (ret != PQOS_RETVAL_OK) - LOG_ERROR("Core assoc reset failed\n"); + ret = resctrl_alloc_cpumask_write(default_cos, &mask); + if (ret != PQOS_RETVAL_OK) + LOG_ERROR("Core assoc reset failed\n"); - return ret; + return ret; } /** @@ -504,58 +503,59 @@ const struct pqos_cap_l2ca *l2_cap, const struct pqos_cap_mba *mba_cap) { - unsigned grps; - unsigned i; - int ret; + unsigned grps; + unsigned i; + int ret; const struct pqos_cap *cap; - LOG_INFO("OS alloc reset - schematas\n"); + LOG_INFO("OS alloc reset - schematas\n"); _pqos_cap_get(&cap, NULL); - ret = resctrl_lock_exclusive(); - if (ret != PQOS_RETVAL_OK) - return ret; - - ret = resctrl_alloc_get_grps_num(cap, &grps); - if (ret != PQOS_RETVAL_OK) - goto os_alloc_reset_light_schematas_exit; - - /** - * Reset schematas - */ - for (i = 0; i < grps; i++) { - struct resctrl_schemata *schmt; + ret = resctrl_lock_exclusive(); + if (ret != PQOS_RETVAL_OK) + return ret; + + ret = resctrl_alloc_get_grps_num(cap, &grps); + if (ret != PQOS_RETVAL_OK) + goto os_alloc_reset_light_schematas_exit; + + /** + * Reset schematas + */ + for (i = 0; i < grps; i++) { + struct resctrl_schemata *schmt; schmt = resctrl_schemata_alloc(cap, m_cpu); if (schmt == NULL) { ret = PQOS_RETVAL_ERROR; LOG_ERROR("Error on schemata memory allocation " - "for resctrl group %u\n", i); + "for resctrl group %u\n", + i); goto os_alloc_reset_light_schematas_exit; - } ret = resctrl_schemata_reset(schmt, l3_cap, l2_cap, mba_cap); if (ret == PQOS_RETVAL_OK) ret = resctrl_alloc_schemata_write(i, schmt); - resctrl_schemata_free(schmt); + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("Error on schemata write " - "for resctrl group %u\n", i); - goto os_alloc_reset_light_schematas_exit; - } - } - - os_alloc_reset_light_schematas_exit: - if (ret != PQOS_RETVAL_OK) - resctrl_lock_release(); - else - ret = resctrl_lock_release(); + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("Error on schemata write " + "for resctrl group %u\n", + i); + goto os_alloc_reset_light_schematas_exit; + } + } + +os_alloc_reset_light_schematas_exit: + if (ret != PQOS_RETVAL_OK) + resctrl_lock_release(); + else + ret = resctrl_lock_release(); - return ret; + return ret; } /** @@ -572,14 +572,14 @@ static int filter_pids(const struct dirent *dir) { - size_t char_idx; + size_t char_idx; - if (dir->d_name[0] == '.') - return 0; + if (dir->d_name[0] == '.') + return 0; for (char_idx = 0; char_idx < strlen(dir->d_name); ++char_idx) { - if (!isdigit(dir->d_name[char_idx])) - return 0; + if (!isdigit(dir->d_name[char_idx])) + return 0; } return 1; @@ -593,37 +593,37 @@ static int os_alloc_reset_tasks(void) { - struct dirent **pids_list = NULL; - int pid_count; - int pid_idx; - int alloc_result = PQOS_RETVAL_ERROR; - pid_t pid; - const int cos0 = 0; - - LOG_INFO("OS alloc reset - tasks\n"); - - pid_count = scandir("/proc", &pids_list, filter_pids, NULL); - - for (pid_idx = 0; pid_idx < pid_count; ++pid_idx) { - pid = atoi(pids_list[pid_idx]->d_name); - alloc_result = os_alloc_assoc_set_pid(pid, cos0); - if (alloc_result == PQOS_RETVAL_PARAM) { - LOG_DEBUG("Task %d no longer exists\n", pid); - alloc_result = PQOS_RETVAL_OK; - } else if (alloc_result != PQOS_RETVAL_OK) { - LOG_ERROR("Error allocating task %d to COS%u\n", - pid, cos0); - break; - } - } - - if (pid_count > 0 && pids_list) { - while (pid_count--) - free(pids_list[pid_count]); - free(pids_list); - } + struct dirent **pids_list = NULL; + int pid_count; + int pid_idx; + int alloc_result = PQOS_RETVAL_ERROR; + pid_t pid; + const int cos0 = 0; + + LOG_INFO("OS alloc reset - tasks\n"); + + pid_count = scandir("/proc", &pids_list, filter_pids, NULL); + + for (pid_idx = 0; pid_idx < pid_count; ++pid_idx) { + pid = atoi(pids_list[pid_idx]->d_name); + alloc_result = os_alloc_assoc_set_pid(pid, cos0); + if (alloc_result == PQOS_RETVAL_PARAM) { + LOG_DEBUG("Task %d no longer exists\n", pid); + alloc_result = PQOS_RETVAL_OK; + } else if (alloc_result != PQOS_RETVAL_OK) { + LOG_ERROR("Error allocating task %d to COS%u\n", pid, + cos0); + break; + } + } - return alloc_result; + if (pid_count > 0 && pids_list) { + while (pid_count--) + free(pids_list[pid_count]); + free(pids_list); + } + + return alloc_result; } /** @@ -643,27 +643,27 @@ */ static int os_alloc_reset_light(const struct pqos_cap_l3ca *l3_cap, - const struct pqos_cap_l2ca *l2_cap, + const struct pqos_cap_l2ca *l2_cap, const struct pqos_cap_mba *mba_cap) { - int ret = PQOS_RETVAL_OK; - int step_result; + int ret = PQOS_RETVAL_OK; + int step_result; - LOG_INFO("OS alloc reset - LIGHT\n"); + LOG_INFO("OS alloc reset - LIGHT\n"); - step_result = os_alloc_reset_cores(); - if (step_result != PQOS_RETVAL_OK) - ret = step_result; + step_result = os_alloc_reset_cores(); + if (step_result != PQOS_RETVAL_OK) + ret = step_result; - step_result = os_alloc_reset_schematas(l3_cap, l2_cap, mba_cap); - if (step_result != PQOS_RETVAL_OK) - ret = step_result; + step_result = os_alloc_reset_schematas(l3_cap, l2_cap, mba_cap); + if (step_result != PQOS_RETVAL_OK) + ret = step_result; - step_result = os_alloc_reset_tasks(); - if (step_result != PQOS_RETVAL_OK) - ret = step_result; + step_result = os_alloc_reset_tasks(); + if (step_result != PQOS_RETVAL_OK) + ret = step_result; - return ret; + return ret; } /** @@ -678,31 +678,31 @@ */ static int l2_cdp_update(const enum pqos_cdp_config l2_cdp_cfg, - const struct pqos_cap_l2ca *l2_cap, - enum pqos_cdp_config *l2_cdp) + const struct pqos_cap_l2ca *l2_cap, + enum pqos_cdp_config *l2_cdp) { int ret = 0; - if (l2_cap == NULL) - return 0; - switch (l2_cdp_cfg) { - case PQOS_REQUIRE_CDP_ON: - *l2_cdp = l2_cdp_cfg; + if (l2_cap == NULL) + return 0; + switch (l2_cdp_cfg) { + case PQOS_REQUIRE_CDP_ON: + *l2_cdp = l2_cdp_cfg; ret = !l2_cap->cdp_on; - break; - case PQOS_REQUIRE_CDP_ANY: + break; + case PQOS_REQUIRE_CDP_ANY: if (l2_cap->cdp_on) *l2_cdp = PQOS_REQUIRE_CDP_ON; else *l2_cdp = PQOS_REQUIRE_CDP_OFF; - break; - case PQOS_REQUIRE_CDP_OFF: - *l2_cdp = l2_cdp_cfg; + break; + case PQOS_REQUIRE_CDP_OFF: + *l2_cdp = l2_cdp_cfg; ret = l2_cap->cdp_on; - break; - } + break; + } - return ret; + return ret; } /** @@ -756,8 +756,8 @@ */ static int mba_cfg_update(const enum pqos_mba_config mba_cfg, - const struct pqos_cap_mba *mba_cap, - enum pqos_mba_config *mba_ctrl) + const struct pqos_cap_mba *mba_cap, + enum pqos_mba_config *mba_ctrl) { int ret = 0; @@ -801,13 +801,13 @@ */ static int os_alloc_reset_full(const enum pqos_cdp_config l3_cdp_cfg, - const enum pqos_cdp_config l2_cdp_cfg, + const enum pqos_cdp_config l2_cdp_cfg, const enum pqos_mba_config mba_cfg, - const struct pqos_cap_l3ca *l3_cap, - const struct pqos_cap_l2ca *l2_cap, + const struct pqos_cap_l3ca *l3_cap, + const struct pqos_cap_l2ca *l2_cap, const struct pqos_cap_mba *mba_cap) { - int ret; + int ret; LOG_INFO("OS alloc reset - FULL\n"); @@ -815,14 +815,14 @@ * Set the CPU assoc back to COS0 */ ret = os_alloc_reset_cores(); - if (ret != PQOS_RETVAL_OK) - goto os_alloc_reset_full_exit; + if (ret != PQOS_RETVAL_OK) + goto os_alloc_reset_full_exit; /** * Umount resctrl to reset schemata */ - LOG_INFO("OS alloc reset - unmount resctrl\n"); + LOG_INFO("OS alloc reset - unmount resctrl\n"); ret = resctrl_umount(); if (ret != PQOS_RETVAL_OK) goto os_alloc_reset_full_exit; @@ -855,7 +855,7 @@ if (ret != PQOS_RETVAL_OK) LOG_ERROR("OS alloc prep error!\n"); - os_alloc_reset_full_exit: +os_alloc_reset_full_exit: return ret; } @@ -884,46 +884,45 @@ l2_cdp_cfg == PQOS_REQUIRE_CDP_OFF || l2_cdp_cfg == PQOS_REQUIRE_CDP_ANY); - ASSERT(mba_cfg == PQOS_MBA_DEFAULT || - mba_cfg == PQOS_MBA_CTRL || + ASSERT(mba_cfg == PQOS_MBA_DEFAULT || mba_cfg == PQOS_MBA_CTRL || mba_cfg == PQOS_MBA_ANY); /* Get L3 CAT capabilities */ - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &alloc_cap); if (alloc_cap != NULL) l3_cap = alloc_cap->u.l3ca; /* Get L2 CAT capabilities */ alloc_cap = NULL; - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &alloc_cap); if (alloc_cap != NULL) l2_cap = alloc_cap->u.l2ca; /* Get MBA capabilities */ alloc_cap = NULL; - (void) _pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &alloc_cap); + (void)_pqos_cap_get_type(PQOS_CAP_TYPE_MBA, &alloc_cap); if (alloc_cap != NULL) mba_cap = alloc_cap->u.mba; /* Check if either L2 CAT or L3 CAT is supported */ if (l2_cap == NULL && l3_cap == NULL && mba_cap == NULL) { - LOG_ERROR("L2 CAT/L3 CAT/MBA not present!\n"); - ret = PQOS_RETVAL_RESOURCE; /* no L2 CAT/L3 CAT/MBA present */ - goto os_alloc_reset_exit; + LOG_ERROR("L2 CAT/L3 CAT/MBA not present!\n"); + ret = PQOS_RETVAL_RESOURCE; /* no L2 CAT/L3 CAT/MBA present */ + goto os_alloc_reset_exit; } /* Check L3 CDP requested while not present */ if (l3_cap == NULL && l3_cdp_cfg != PQOS_REQUIRE_CDP_ANY) { - LOG_ERROR("L3 CDP setting requested but no L3 CAT present!\n"); - ret = PQOS_RETVAL_RESOURCE; - goto os_alloc_reset_exit; + LOG_ERROR("L3 CDP setting requested but no L3 CAT present!\n"); + ret = PQOS_RETVAL_RESOURCE; + goto os_alloc_reset_exit; } /* Check against erroneous CDP request */ if (l3_cap != NULL && l3_cdp_cfg == PQOS_REQUIRE_CDP_ON && - !l3_cap->cdp) { - LOG_ERROR("L3 CAT/CDP requested but not supported by the " + !l3_cap->cdp) { + LOG_ERROR("L3 CAT/CDP requested but not supported by the " "platform!\n"); - ret = PQOS_RETVAL_PARAM; - goto os_alloc_reset_exit; + ret = PQOS_RETVAL_PARAM; + goto os_alloc_reset_exit; } /* Check L2 CDP requested while not present */ if (l2_cap == NULL && l2_cdp_cfg != PQOS_REQUIRE_CDP_ANY) { @@ -933,7 +932,7 @@ } /* Check against erroneous L2 CDP request */ if (l2_cap != NULL && l2_cdp_cfg == PQOS_REQUIRE_CDP_ON && - !l2_cap->cdp) { + !l2_cap->cdp) { LOG_ERROR("L2 CAT/CDP requested but not supported by the " "platform!\n"); ret = PQOS_RETVAL_PARAM; @@ -946,8 +945,7 @@ goto os_alloc_reset_exit; } /* Check against erroneous MBA CTRL request */ - if (mba_cap != NULL && mba_cfg == PQOS_MBA_CTRL && - mba_cap->ctrl == 0) { + if (mba_cap != NULL && mba_cfg == PQOS_MBA_CTRL && mba_cap->ctrl == 0) { LOG_ERROR("MBA CTRL requested but not supported!\n"); ret = PQOS_RETVAL_PARAM; goto os_alloc_reset_exit; @@ -965,27 +963,27 @@ if (l3_cdp_changed || l2_cdp_changed || mba_changed) { - unsigned monitoring_active = 0; + unsigned monitoring_active = 0; - ret = resctrl_mon_active(&monitoring_active); - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("Failed to check resctrl " - "monitoring activity\n"); - goto os_alloc_reset_exit; - } - - if (monitoring_active > 0) { - LOG_ERROR("Failed to reset allocation. Please stop " - "monitoring in order to change CDP/MBA " + ret = resctrl_mon_active(&monitoring_active); + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("Failed to check resctrl " + "monitoring activity\n"); + goto os_alloc_reset_exit; + } + + if (monitoring_active > 0) { + LOG_ERROR("Failed to reset allocation. Please stop " + "monitoring in order to change CDP/MBA " "settings\n"); - ret = PQOS_RETVAL_ERROR; - } else - ret = os_alloc_reset_full(l3_cdp, l2_cdp, mba_ctrl, + ret = PQOS_RETVAL_ERROR; + } else + ret = os_alloc_reset_full(l3_cdp, l2_cdp, mba_ctrl, l3_cap, l2_cap, mba_cap); } else - ret = os_alloc_reset_light(l3_cap, l2_cap, mba_cap); + ret = os_alloc_reset_light(l3_cap, l2_cap, mba_cap); - os_alloc_reset_exit: +os_alloc_reset_exit: return ret; } @@ -1001,25 +999,25 @@ static int verify_l3cat_id(const unsigned l3cat_id, const struct pqos_cpuinfo *cpu) { - int ret = PQOS_RETVAL_PARAM; - unsigned i; - unsigned l3cat_num; - unsigned *l3cat_ids; - - /* Get l3cat ids in the system */ - l3cat_ids = pqos_cpu_get_l3cat_ids(cpu, &l3cat_num); - if (l3cat_ids == NULL) - return PQOS_RETVAL_ERROR; - - for (i = 0; i < l3cat_num; ++i) - if (l3cat_id == l3cat_ids[i]) { - ret = PQOS_RETVAL_OK; - break; - } + int ret = PQOS_RETVAL_PARAM; + unsigned i; + unsigned l3cat_num; + unsigned *l3cat_ids; + + /* Get l3cat ids in the system */ + l3cat_ids = pqos_cpu_get_l3cat_ids(cpu, &l3cat_num); + if (l3cat_ids == NULL) + return PQOS_RETVAL_ERROR; + + for (i = 0; i < l3cat_num; ++i) + if (l3cat_id == l3cat_ids[i]) { + ret = PQOS_RETVAL_OK; + break; + } - free(l3cat_ids); + free(l3cat_ids); - return ret; + return ret; } /* @@ -1034,25 +1032,25 @@ static int verify_mba_id(const unsigned mba_id, const struct pqos_cpuinfo *cpu) { - int ret = PQOS_RETVAL_PARAM; - unsigned i; - unsigned mba_id_num; - unsigned *mba_ids; - - /* Get mba ids in the system */ - mba_ids = pqos_cpu_get_mba_ids(cpu, &mba_id_num); - if (mba_ids == NULL) - return PQOS_RETVAL_ERROR; - - for (i = 0; i < mba_id_num; ++i) - if (mba_id == mba_ids[i]) { - ret = PQOS_RETVAL_OK; - break; - } + int ret = PQOS_RETVAL_PARAM; + unsigned i; + unsigned mba_id_num; + unsigned *mba_ids; + + /* Get mba ids in the system */ + mba_ids = pqos_cpu_get_mba_ids(cpu, &mba_id_num); + if (mba_ids == NULL) + return PQOS_RETVAL_ERROR; + + for (i = 0; i < mba_id_num; ++i) + if (mba_id == mba_ids[i]) { + ret = PQOS_RETVAL_OK; + break; + } - free(mba_ids); + free(mba_ids); - return ret; + return ret; } int @@ -1060,90 +1058,90 @@ const unsigned num_cos, const struct pqos_l3ca *ca) { - int ret; - unsigned i; - unsigned num_grps = 0, l3ca_num; - int cdp_enabled = 0; + int ret; + unsigned i; + unsigned num_grps = 0, l3ca_num; + int cdp_enabled = 0; const struct pqos_cap *cap; const struct pqos_cpuinfo *cpu; - ASSERT(ca != NULL); - ASSERT(num_cos != 0); + ASSERT(ca != NULL); + ASSERT(num_cos != 0); _pqos_cap_get(&cap, &cpu); - ret = pqos_l3ca_get_cos_num(cap, &l3ca_num); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* L3 CAT not supported */ - - ret = resctrl_alloc_get_grps_num(cap, &num_grps); - if (ret != PQOS_RETVAL_OK) - return ret; + ret = pqos_l3ca_get_cos_num(cap, &l3ca_num); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* L3 CAT not supported */ - if (num_cos > num_grps) - return PQOS_RETVAL_ERROR; + ret = resctrl_alloc_get_grps_num(cap, &num_grps); + if (ret != PQOS_RETVAL_OK) + return ret; + + if (num_cos > num_grps) + return PQOS_RETVAL_ERROR; - ret = verify_l3cat_id(l3cat_id, cpu); + ret = verify_l3cat_id(l3cat_id, cpu); if (ret != PQOS_RETVAL_OK) goto os_l3ca_set_exit; - ret = pqos_l3ca_cdp_enabled(cap, NULL, &cdp_enabled); - if (ret != PQOS_RETVAL_OK) - goto os_l3ca_set_exit; + ret = pqos_l3ca_cdp_enabled(cap, NULL, &cdp_enabled); + if (ret != PQOS_RETVAL_OK) + goto os_l3ca_set_exit; ret = resctrl_lock_exclusive(); if (ret != PQOS_RETVAL_OK) goto os_l3ca_set_exit; - for (i = 0; i < num_cos; i++) { - struct resctrl_schemata *schmt; + for (i = 0; i < num_cos; i++) { + struct resctrl_schemata *schmt; - if (ca[i].cdp == 1 && cdp_enabled == 0) { - LOG_ERROR("Attempting to set CDP COS while L3 CDP " - "is disabled!\n"); - ret = PQOS_RETVAL_ERROR; - goto os_l3ca_set_unlock; - } + if (ca[i].cdp == 1 && cdp_enabled == 0) { + LOG_ERROR("Attempting to set CDP COS while L3 CDP " + "is disabled!\n"); + ret = PQOS_RETVAL_ERROR; + goto os_l3ca_set_unlock; + } - schmt = resctrl_schemata_alloc(cap, cpu); + schmt = resctrl_schemata_alloc(cap, cpu); if (schmt == NULL) ret = PQOS_RETVAL_ERROR; - /* read schemata file */ - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_read(ca[i].class_id, - schmt); + /* read schemata file */ + if (ret == PQOS_RETVAL_OK) + ret = + resctrl_alloc_schemata_read(ca[i].class_id, schmt); /* update schemata */ if (ret == PQOS_RETVAL_OK) { struct pqos_l3ca l3ca; - if (cdp_enabled == 1 && ca[i].cdp == 0) { - l3ca.cdp = 1; - l3ca.u.s.data_mask = ca[i].u.ways_mask; - l3ca.u.s.code_mask = ca[i].u.ways_mask; - } else - l3ca = ca[i]; + if (cdp_enabled == 1 && ca[i].cdp == 0) { + l3ca.cdp = 1; + l3ca.u.s.data_mask = ca[i].u.ways_mask; + l3ca.u.s.code_mask = ca[i].u.ways_mask; + } else + l3ca = ca[i]; - ret = resctrl_schemata_l3ca_set(schmt, l3cat_id, &l3ca); + ret = resctrl_schemata_l3ca_set(schmt, l3cat_id, &l3ca); } - /* write schemata */ - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_write(ca[i].class_id, - schmt); + /* write schemata */ + if (ret == PQOS_RETVAL_OK) + ret = + resctrl_alloc_schemata_write(ca[i].class_id, schmt); - resctrl_schemata_free(schmt); + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) - goto os_l3ca_set_unlock; - } + if (ret != PQOS_RETVAL_OK) + goto os_l3ca_set_unlock; + } - os_l3ca_set_unlock: +os_l3ca_set_unlock: resctrl_lock_release(); - os_l3ca_set_exit: - return ret; +os_l3ca_set_exit: + return ret; } int @@ -1152,30 +1150,30 @@ unsigned *num_ca, struct pqos_l3ca *ca) { - int ret; - unsigned class_id; - unsigned count = 0; + int ret; + unsigned class_id; + unsigned count = 0; const struct pqos_cap *cap; const struct pqos_cpuinfo *cpu; - ASSERT(num_ca != NULL); - ASSERT(ca != NULL); - ASSERT(max_num_ca != 0); + ASSERT(num_ca != NULL); + ASSERT(ca != NULL); + ASSERT(max_num_ca != 0); _pqos_cap_get(&cap, &cpu); - ret = pqos_l3ca_get_cos_num(cap, &count); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* L3 CAT not supported */ - - ret = resctrl_alloc_get_grps_num(cap, &count); - if (ret != PQOS_RETVAL_OK) - return ret; + ret = pqos_l3ca_get_cos_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* L3 CAT not supported */ + + ret = resctrl_alloc_get_grps_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return ret; - if (count > max_num_ca) - return PQOS_RETVAL_ERROR; + if (count > max_num_ca) + return PQOS_RETVAL_ERROR; - ret = verify_l3cat_id(l3cat_id, cpu); + ret = verify_l3cat_id(l3cat_id, cpu); if (ret != PQOS_RETVAL_OK) goto os_l3ca_get_exit; @@ -1194,55 +1192,55 @@ ret = resctrl_alloc_schemata_read(class_id, schmt); if (ret == PQOS_RETVAL_OK) - ret = resctrl_schemata_l3ca_get(schmt, l3cat_id, + ret = resctrl_schemata_l3ca_get(schmt, l3cat_id, &ca[class_id]); ca[class_id].class_id = class_id; - resctrl_schemata_free(schmt); + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) - goto os_l3ca_get_unlock; - } - *num_ca = count; + if (ret != PQOS_RETVAL_OK) + goto os_l3ca_get_unlock; + } + *num_ca = count; - os_l3ca_get_unlock: +os_l3ca_get_unlock: resctrl_lock_release(); - os_l3ca_get_exit: - return ret; +os_l3ca_get_exit: + return ret; } int os_l3ca_get_min_cbm_bits(unsigned *min_cbm_bits) { - int ret = PQOS_RETVAL_OK; - char buf[128]; - const struct pqos_capability *l3_cap = NULL; - FILE *fd; + int ret = PQOS_RETVAL_OK; + char buf[128]; + const struct pqos_capability *l3_cap = NULL; + FILE *fd; - ASSERT(min_cbm_bits != NULL); + ASSERT(min_cbm_bits != NULL); - /** - * Get L3 CAT capabilities - */ - ret = _pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &l3_cap); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* L3 CAT not supported */ + /** + * Get L3 CAT capabilities + */ + ret = _pqos_cap_get_type(PQOS_CAP_TYPE_L3CA, &l3_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* L3 CAT not supported */ - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s/info/L3/min_cbm_bits", RESCTRL_PATH); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s/info/L3/min_cbm_bits", RESCTRL_PATH); - fd = fopen_check_symlink(buf, "r"); - if (fd == NULL) - return PQOS_RETVAL_ERROR; + fd = pqos_fopen(buf, "r"); + if (fd == NULL) + return PQOS_RETVAL_ERROR; - if (fscanf(fd, "%u", min_cbm_bits) != 1) - ret = PQOS_RETVAL_ERROR; + if (fscanf(fd, "%u", min_cbm_bits) != 1) + ret = PQOS_RETVAL_ERROR; - fclose(fd); + fclose(fd); - return ret; + return ret; } /* @@ -1283,43 +1281,43 @@ const unsigned num_cos, const struct pqos_l2ca *ca) { - int ret; - unsigned i; - unsigned num_grps = 0, l2ca_num; + int ret; + unsigned i; + unsigned num_grps = 0, l2ca_num; int cdp_enabled; const struct pqos_cap *cap; const struct pqos_cpuinfo *cpu; - ASSERT(ca != NULL); - ASSERT(num_cos != 0); + ASSERT(ca != NULL); + ASSERT(num_cos != 0); _pqos_cap_get(&cap, &cpu); - ret = pqos_l2ca_get_cos_num(cap, &l2ca_num); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ - - ret = resctrl_alloc_get_grps_num(cap, &num_grps); - if (ret != PQOS_RETVAL_OK) - return ret; + ret = pqos_l2ca_get_cos_num(cap, &l2ca_num); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ - if (num_cos > num_grps) - return PQOS_RETVAL_PARAM; + ret = resctrl_alloc_get_grps_num(cap, &num_grps); + if (ret != PQOS_RETVAL_OK) + return ret; + + if (num_cos > num_grps) + return PQOS_RETVAL_PARAM; ret = pqos_l2ca_cdp_enabled(cap, NULL, &cdp_enabled); if (ret != PQOS_RETVAL_OK) goto os_l2ca_set_exit; - /* - * Check if class id's are within allowed range. - */ - for (i = 0; i < num_cos; i++) { - if (ca[i].class_id >= l2ca_num) { - LOG_ERROR("L2 COS%u is out of range (COS%u is max)!\n", - ca[i].class_id, l2ca_num - 1); - return PQOS_RETVAL_PARAM; - } - } + /* + * Check if class id's are within allowed range. + */ + for (i = 0; i < num_cos; i++) { + if (ca[i].class_id >= l2ca_num) { + LOG_ERROR("L2 COS%u is out of range (COS%u is max)!\n", + ca[i].class_id, l2ca_num - 1); + return PQOS_RETVAL_PARAM; + } + } ret = verify_l2_id(l2id, cpu); if (ret != PQOS_RETVAL_OK) @@ -1329,8 +1327,8 @@ if (ret != PQOS_RETVAL_OK) goto os_l2ca_set_exit; - for (i = 0; i < num_cos; i++) { - struct resctrl_schemata *schmt; + for (i = 0; i < num_cos; i++) { + struct resctrl_schemata *schmt; if (ca[i].cdp == 1 && cdp_enabled == 0) { LOG_ERROR("Attempting to set CDP COS while L2 CDP " @@ -1339,14 +1337,14 @@ goto os_l2ca_set_unlock; } - schmt = resctrl_schemata_alloc(cap, cpu); + schmt = resctrl_schemata_alloc(cap, cpu); if (schmt == NULL) ret = PQOS_RETVAL_ERROR; - /* read schemata file */ - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_read(ca[i].class_id, - schmt); + /* read schemata file */ + if (ret == PQOS_RETVAL_OK) + ret = + resctrl_alloc_schemata_read(ca[i].class_id, schmt); /* update schemata */ if (ret == PQOS_RETVAL_OK) { @@ -1363,20 +1361,20 @@ } if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_write(ca[i].class_id, - schmt); + ret = + resctrl_alloc_schemata_write(ca[i].class_id, schmt); - resctrl_schemata_free(schmt); + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) - goto os_l2ca_set_unlock; - } + if (ret != PQOS_RETVAL_OK) + goto os_l2ca_set_unlock; + } - os_l2ca_set_unlock: +os_l2ca_set_unlock: resctrl_lock_release(); - os_l2ca_set_exit: - return ret; +os_l2ca_set_exit: + return ret; } int @@ -1385,29 +1383,29 @@ unsigned *num_ca, struct pqos_l2ca *ca) { - int ret; - unsigned class_id; - unsigned count = 0; + int ret; + unsigned class_id; + unsigned count = 0; const struct pqos_cap *cap; const struct pqos_cpuinfo *cpu; - ASSERT(num_ca != NULL); - ASSERT(ca != NULL); - ASSERT(max_num_ca != 0); + ASSERT(num_ca != NULL); + ASSERT(ca != NULL); + ASSERT(max_num_ca != 0); _pqos_cap_get(&cap, &cpu); - ret = pqos_l2ca_get_cos_num(cap, &count); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ - - ret = resctrl_alloc_get_grps_num(cap, &count); - if (ret != PQOS_RETVAL_OK) - return ret; - - if (count > max_num_ca) - /* Not enough space to store the classes */ - return PQOS_RETVAL_PARAM; + ret = pqos_l2ca_get_cos_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ + + ret = resctrl_alloc_get_grps_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return ret; + + if (count > max_num_ca) + /* Not enough space to store the classes */ + return PQOS_RETVAL_PARAM; ret = verify_l2_id(l2id, cpu); if (ret != PQOS_RETVAL_OK) @@ -1417,15 +1415,15 @@ if (ret != PQOS_RETVAL_OK) goto os_l2ca_get_exit; - for (class_id = 0; class_id < count; class_id++) { - struct resctrl_schemata *schmt; + for (class_id = 0; class_id < count; class_id++) { + struct resctrl_schemata *schmt; - schmt = resctrl_schemata_alloc(cap, cpu); + schmt = resctrl_schemata_alloc(cap, cpu); if (schmt == NULL) ret = PQOS_RETVAL_ERROR; - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_read(class_id, schmt); + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read(class_id, schmt); if (ret == PQOS_RETVAL_OK) ret = resctrl_schemata_l2ca_get(schmt, l2id, @@ -1433,50 +1431,50 @@ ca[class_id].class_id = class_id; - resctrl_schemata_free(schmt); + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) - goto os_l2ca_get_unlock; - } - *num_ca = count; + if (ret != PQOS_RETVAL_OK) + goto os_l2ca_get_unlock; + } + *num_ca = count; - os_l2ca_get_unlock: +os_l2ca_get_unlock: resctrl_lock_release(); - os_l2ca_get_exit: - return ret; +os_l2ca_get_exit: + return ret; } int os_l2ca_get_min_cbm_bits(unsigned *min_cbm_bits) { - int ret; - char buf[128]; - const struct pqos_capability *l2_cap = NULL; - FILE *fd; + int ret; + char buf[128]; + const struct pqos_capability *l2_cap = NULL; + FILE *fd; - ASSERT(min_cbm_bits != NULL); + ASSERT(min_cbm_bits != NULL); - /** - * Get L2 CAT capabilities - */ - ret = _pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &l2_cap); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ + /** + * Get L2 CAT capabilities + */ + ret = _pqos_cap_get_type(PQOS_CAP_TYPE_L2CA, &l2_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* L2 CAT not supported */ - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s/info/L2/min_cbm_bits", RESCTRL_PATH); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s/info/L2/min_cbm_bits", RESCTRL_PATH); - fd = fopen_check_symlink(buf, "r"); - if (fd == NULL) - return PQOS_RETVAL_ERROR; + fd = pqos_fopen(buf, "r"); + if (fd == NULL) + return PQOS_RETVAL_ERROR; - if (fscanf(fd, "%u", min_cbm_bits) != 1) - ret = PQOS_RETVAL_ERROR; + if (fscanf(fd, "%u", min_cbm_bits) != 1) + ret = PQOS_RETVAL_ERROR; - fclose(fd); + fclose(fd); - return ret; + return ret; } int @@ -1485,45 +1483,45 @@ const struct pqos_mba *requested, struct pqos_mba *actual) { - int ret; - unsigned i, step = 0; - unsigned num_grps = 0; + int ret; + unsigned i, step = 0; + unsigned num_grps = 0; const struct pqos_cap *cap; const struct pqos_cpuinfo *cpu; - const struct pqos_capability *mba_cap = NULL; + const struct pqos_capability *mba_cap = NULL; - ASSERT(requested != NULL); - ASSERT(num_cos != 0); + ASSERT(requested != NULL); + ASSERT(num_cos != 0); _pqos_cap_get(&cap, &cpu); - /** - * Check if MBA is supported - */ - ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* MBA not supported */ - - ret = resctrl_alloc_get_grps_num(cap, &num_grps); - if (ret != PQOS_RETVAL_OK) - return ret; + /** + * Check if MBA is supported + */ + ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* MBA not supported */ + + ret = resctrl_alloc_get_grps_num(cap, &num_grps); + if (ret != PQOS_RETVAL_OK) + return ret; - if (num_cos > num_grps) - return PQOS_RETVAL_PARAM; + if (num_cos > num_grps) + return PQOS_RETVAL_PARAM; step = mba_cap->u.mba->throttle_step; /** - * Check if class id's are within allowed range. - */ - for (i = 0; i < num_cos; i++) - if (requested[i].class_id >= num_grps) { - LOG_ERROR("MBA COS%u is out of range (COS%u is max)!\n", - requested[i].class_id, num_grps - 1); - return PQOS_RETVAL_PARAM; - } + * Check if class id's are within allowed range. + */ + for (i = 0; i < num_cos; i++) + if (requested[i].class_id >= num_grps) { + LOG_ERROR("MBA COS%u is out of range (COS%u is max)!\n", + requested[i].class_id, num_grps - 1); + return PQOS_RETVAL_PARAM; + } - ret = verify_mba_id(mba_id, cpu); + ret = verify_mba_id(mba_id, cpu); if (ret != PQOS_RETVAL_OK) goto os_mba_set_exit; @@ -1531,77 +1529,193 @@ if (ret != PQOS_RETVAL_OK) goto os_mba_set_exit; - for (i = 0; i < num_cos; i++) { - struct resctrl_schemata *schmt; + for (i = 0; i < num_cos; i++) { + struct resctrl_schemata *schmt; - if (mba_cap->u.mba->ctrl_on == 0 && requested[i].ctrl) { - LOG_ERROR("MBA controller requested but" - " not enabled!\n"); - ret = PQOS_RETVAL_PARAM; - goto os_mba_set_unlock; - } - - if (mba_cap->u.mba->ctrl_on == 1 && !requested[i].ctrl) { - LOG_ERROR("Expected MBA controller but" - " not requested!\n"); - ret = PQOS_RETVAL_PARAM; - goto os_mba_set_unlock; - } + if (mba_cap->u.mba->ctrl_on == 0 && requested[i].ctrl) { + LOG_ERROR("MBA controller requested but" + " not enabled!\n"); + ret = PQOS_RETVAL_PARAM; + goto os_mba_set_unlock; + } - schmt = resctrl_schemata_alloc(cap, cpu); + if (mba_cap->u.mba->ctrl_on == 1 && !requested[i].ctrl) { + LOG_ERROR("Expected MBA controller but" + " not requested!\n"); + ret = PQOS_RETVAL_PARAM; + goto os_mba_set_unlock; + } + + schmt = resctrl_schemata_alloc(cap, cpu); if (schmt == NULL) ret = PQOS_RETVAL_ERROR; - /* read schemata file */ - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_read(requested[i].class_id, - schmt); - - /* update and write schemata */ - if (ret == PQOS_RETVAL_OK) { - struct pqos_mba mba; - - mba = requested[i]; - - if (mba.ctrl == 0) { - mba.mb_max = (((requested[i].mb_max - + (step/2)) / step) * step); + /* read schemata file */ + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read(requested[i].class_id, + schmt); + + /* update and write schemata */ + if (ret == PQOS_RETVAL_OK) { + struct pqos_mba mba; + + mba = requested[i]; + + if (mba.ctrl == 0) { + mba.mb_max = + (((requested[i].mb_max + (step / 2)) / + step) * + step); if (mba.mb_max == 0) mba.mb_max = step; - } + } - ret = resctrl_schemata_mba_set(schmt, mba_id, &mba); + ret = resctrl_schemata_mba_set(schmt, mba_id, &mba); } /* write schemata */ if (ret == PQOS_RETVAL_OK) ret = resctrl_alloc_schemata_write( - requested[i].class_id, schmt); + requested[i].class_id, schmt); - if (actual != NULL) { - /* read actual schemata */ - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_read( - requested[i].class_id, schmt); + if (actual != NULL) { + /* read actual schemata */ + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read( + requested[i].class_id, schmt); - /* update actual schemata */ + /* update actual schemata */ if (ret == PQOS_RETVAL_OK) { - ret = resctrl_schemata_mba_get(schmt, mba_id, + ret = resctrl_schemata_mba_get(schmt, mba_id, &actual[i]); actual[i].class_id = requested[i].class_id; } - } - resctrl_schemata_free(schmt); + } + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) - goto os_mba_set_unlock; - } + if (ret != PQOS_RETVAL_OK) + goto os_mba_set_unlock; + } - os_mba_set_unlock: +os_mba_set_unlock: resctrl_lock_release(); - os_mba_set_exit: - return ret; +os_mba_set_exit: + return ret; +} + +int +os_mba_set_amd(const unsigned mba_id, + const unsigned num_cos, + const struct pqos_mba *requested, + struct pqos_mba *actual) +{ + int ret; + unsigned i; + unsigned num_grps = 0; + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + const struct pqos_capability *mba_cap = NULL; + + ASSERT(requested != NULL); + ASSERT(num_cos != 0); + + _pqos_cap_get(&cap, &cpu); + + /** + * Check if MBA is supported + */ + ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* MBA not supported */ + + ret = resctrl_alloc_get_grps_num(cap, &num_grps); + if (ret != PQOS_RETVAL_OK) + return ret; + + if (num_cos > num_grps) + return PQOS_RETVAL_PARAM; + + /** + * Check if class id's are within allowed range. + */ + for (i = 0; i < num_cos; i++) + if (requested[i].class_id >= num_grps) { + LOG_ERROR("MBA COS%u is out of range (COS%u is max)!\n", + requested[i].class_id, num_grps - 1); + return PQOS_RETVAL_PARAM; + } + + ret = verify_mba_id(mba_id, cpu); + if (ret != PQOS_RETVAL_OK) + goto os_mba_set_exit; + + ret = resctrl_lock_exclusive(); + if (ret != PQOS_RETVAL_OK) + goto os_mba_set_exit; + + for (i = 0; i < num_cos; i++) { + struct resctrl_schemata *schmt; + + if (mba_cap->u.mba->ctrl_on == 0 && requested[i].ctrl) { + LOG_ERROR("MBA controller requested but not " + "enabled!\n"); + ret = PQOS_RETVAL_PARAM; + goto os_mba_set_unlock; + } + + if (mba_cap->u.mba->ctrl_on == 1 && !requested[i].ctrl) { + LOG_ERROR("Expected MBA controller but not " + "requested!\n"); + ret = PQOS_RETVAL_PARAM; + goto os_mba_set_unlock; + } + + schmt = resctrl_schemata_alloc(cap, cpu); + if (schmt == NULL) + ret = PQOS_RETVAL_ERROR; + + /* read schemata file */ + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read(requested[i].class_id, + schmt); + + /* update and write schemata */ + if (ret == PQOS_RETVAL_OK) { + struct pqos_mba mba = requested[i]; + + ret = resctrl_schemata_mba_set(schmt, mba_id, &mba); + } + + /* write schemata */ + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_write( + requested[i].class_id, schmt); + + if (actual != NULL) { + /* read actual schemata */ + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read( + requested[i].class_id, schmt); + + /* update actual schemata */ + if (ret == PQOS_RETVAL_OK) { + ret = resctrl_schemata_mba_get(schmt, mba_id, + &actual[i]); + actual[i].class_id = requested[i].class_id; + } + } + resctrl_schemata_free(schmt); + + if (ret != PQOS_RETVAL_OK) + goto os_mba_set_unlock; + } + +os_mba_set_unlock: + resctrl_lock_release(); + +os_mba_set_exit: + return ret; } int @@ -1610,34 +1724,105 @@ unsigned *num_cos, struct pqos_mba *mba_tab) { - int ret; - unsigned class_id; - unsigned count = 0; + int ret; + unsigned class_id; + unsigned count = 0; + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + const struct pqos_capability *mba_cap = NULL; + + ASSERT(num_cos != NULL); + ASSERT(max_num_cos != 0); + ASSERT(mba_tab != NULL); + + _pqos_cap_get(&cap, &cpu); + + /** + * Check if MBA is supported + */ + ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* MBA not supported */ + + ret = resctrl_alloc_get_grps_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return ret; + + if (count > max_num_cos) + return PQOS_RETVAL_ERROR; + + ret = verify_mba_id(mba_id, cpu); + if (ret != PQOS_RETVAL_OK) + goto os_mba_get_exit; + + ret = resctrl_lock_shared(); + if (ret != PQOS_RETVAL_OK) + goto os_mba_get_exit; + + for (class_id = 0; class_id < count; class_id++) { + struct resctrl_schemata *schmt; + + schmt = resctrl_schemata_alloc(cap, cpu); + if (schmt == NULL) + ret = PQOS_RETVAL_ERROR; + + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read(class_id, schmt); + + if (ret == PQOS_RETVAL_OK) + ret = resctrl_schemata_mba_get(schmt, mba_id, + &mba_tab[class_id]); + + mba_tab[class_id].class_id = class_id; + + resctrl_schemata_free(schmt); + + if (ret != PQOS_RETVAL_OK) + goto os_mba_get_unlock; + } + *num_cos = count; + +os_mba_get_unlock: + resctrl_lock_release(); + +os_mba_get_exit: + return ret; +} + +int +os_mba_get_amd(const unsigned mba_id, + const unsigned max_num_cos, + unsigned *num_cos, + struct pqos_mba *mba_tab) +{ + int ret; + unsigned class_id; + unsigned count = 0; const struct pqos_cap *cap; const struct pqos_cpuinfo *cpu; - const struct pqos_capability *mba_cap = NULL; + const struct pqos_capability *mba_cap = NULL; - ASSERT(num_cos != NULL); - ASSERT(max_num_cos != 0); - ASSERT(mba_tab != NULL); + ASSERT(num_cos != NULL); + ASSERT(max_num_cos != 0); + ASSERT(mba_tab != NULL); _pqos_cap_get(&cap, &cpu); - /** - * Check if MBA is supported - */ - ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); - if (ret != PQOS_RETVAL_OK) - return PQOS_RETVAL_RESOURCE; /* MBA not supported */ - - ret = resctrl_alloc_get_grps_num(cap, &count); - if (ret != PQOS_RETVAL_OK) - return ret; + /** + * Check if MBA is supported + */ + ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); + if (ret != PQOS_RETVAL_OK) + return PQOS_RETVAL_RESOURCE; /* MBA not supported */ + + ret = resctrl_alloc_get_grps_num(cap, &count); + if (ret != PQOS_RETVAL_OK) + return ret; - if (count > max_num_cos) - return PQOS_RETVAL_ERROR; + if (count > max_num_cos) + return PQOS_RETVAL_ERROR; - ret = verify_mba_id(mba_id, cpu); + ret = verify_mba_id(mba_id, cpu); if (ret != PQOS_RETVAL_OK) goto os_mba_get_exit; @@ -1645,52 +1830,51 @@ if (ret != PQOS_RETVAL_OK) goto os_mba_get_exit; - for (class_id = 0; class_id < count; class_id++) { - struct resctrl_schemata *schmt; + for (class_id = 0; class_id < count; class_id++) { + struct resctrl_schemata *schmt; - schmt = resctrl_schemata_alloc(cap, cpu); + schmt = resctrl_schemata_alloc(cap, cpu); if (schmt == NULL) ret = PQOS_RETVAL_ERROR; - if (ret == PQOS_RETVAL_OK) - ret = resctrl_alloc_schemata_read(class_id, schmt); + if (ret == PQOS_RETVAL_OK) + ret = resctrl_alloc_schemata_read(class_id, schmt); - if (ret == PQOS_RETVAL_OK) - ret = resctrl_schemata_mba_get(schmt, mba_id, - &mba_tab[class_id]); + if (ret == PQOS_RETVAL_OK) + ret = resctrl_schemata_mba_get(schmt, mba_id, + &mba_tab[class_id]); mba_tab[class_id].class_id = class_id; - resctrl_schemata_free(schmt); + resctrl_schemata_free(schmt); - if (ret != PQOS_RETVAL_OK) - goto os_mba_get_unlock; - } - *num_cos = count; + if (ret != PQOS_RETVAL_OK) + goto os_mba_get_unlock; + } + *num_cos = count; - os_mba_get_unlock: +os_mba_get_unlock: resctrl_lock_release(); - os_mba_get_exit: - return ret; +os_mba_get_exit: + return ret; } int -os_alloc_assoc_set_pid(const pid_t task, - const unsigned class_id) +os_alloc_assoc_set_pid(const pid_t task, const unsigned class_id) { int ret; - unsigned max_cos = 0; + unsigned max_cos = 0; int ret_mon; char mon_group[256]; const struct pqos_cap *cap; _pqos_cap_get(&cap, NULL); - /* Get number of COS */ + /* Get number of COS */ ret = resctrl_alloc_get_grps_num(cap, &max_cos); - if (ret != PQOS_RETVAL_OK) - return ret; + if (ret != PQOS_RETVAL_OK) + return ret; if (class_id >= max_cos) { LOG_ERROR("COS out of bounds for task %d\n", (int)task); @@ -1708,7 +1892,8 @@ ret_mon = resctrl_mon_assoc_get_pid(task, mon_group, sizeof(mon_group)); if (ret_mon != PQOS_RETVAL_OK && ret_mon != PQOS_RETVAL_RESOURCE) LOG_WARN("Failed to obtain monitoring group assignment for " - "task %d\n", task); + "task %d\n", + task); /* Write to tasks file */ ret = resctrl_alloc_assoc_set_pid(task, class_id); @@ -1720,18 +1905,18 @@ ret_mon = resctrl_mon_assoc_set_pid(task, mon_group); if (ret_mon != PQOS_RETVAL_OK) LOG_WARN("Could not assign task %d back to monitoring " - "group\n", task); + "group\n", + task); } - os_alloc_assoc_set_pid_exit: +os_alloc_assoc_set_pid_exit: resctrl_lock_release(); return ret; } int -os_alloc_assoc_get_pid(const pid_t task, - unsigned *class_id) +os_alloc_assoc_get_pid(const pid_t task, unsigned *class_id) { int ret; @@ -1759,7 +1944,6 @@ int ret; const struct pqos_cap *cap; - ASSERT(task_num > 0); ASSERT(task_array != NULL); ASSERT(class_id != NULL); @@ -1791,18 +1975,17 @@ goto os_alloc_assign_pid_unlock; } - os_alloc_assign_pid_unlock: +os_alloc_assign_pid_unlock: resctrl_lock_release(); return ret; } int -os_alloc_release_pid(const pid_t *task_array, - const unsigned task_num) +os_alloc_release_pid(const pid_t *task_array, const unsigned task_num) { unsigned i; - int ret; + int ret; ASSERT(task_array != NULL); ASSERT(task_num != 0); @@ -1818,11 +2001,11 @@ */ for (i = 0; i < task_num; i++) { ret = resctrl_alloc_task_write(0, task_array[i]); - if (ret != PQOS_RETVAL_OK) + if (ret != PQOS_RETVAL_OK) goto os_alloc_release_pid_unlock; - } + } - os_alloc_release_pid_unlock: +os_alloc_release_pid_unlock: resctrl_lock_release(); return ret; diff -Nru intel-cmt-cat-3.2/lib/os_allocation.h intel-cmt-cat-4.0/lib/os_allocation.h --- intel-cmt-cat-3.2/lib/os_allocation.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/os_allocation.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,8 +95,7 @@ * * @return Operations status */ -int os_alloc_release(const unsigned *core_array, - const unsigned core_num); +int os_alloc_release(const unsigned *core_array, const unsigned core_num); /** * @brief Assign first available COS to tasks in \a task_array @@ -132,8 +131,7 @@ * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int os_alloc_release_pid(const pid_t *task_array, - const unsigned task_num); +int os_alloc_release_pid(const pid_t *task_array, const unsigned task_num); /** * @brief OS interface to reset configuration of allocation technologies @@ -244,7 +242,7 @@ /** * @brief OS interface to set classes of service - * defined by \a MBA id + * defined by \a mba_id * * @param [in] mba_id MBA resource id * @param [in] num_cos number of classes of service at \a ca @@ -260,6 +258,23 @@ struct pqos_mba *actual); /** + * @brief OS interface to set classes of service defined by \a mba_id + * @NOTE: This function is specific to AMD + * + * @param [in] mba_id MBA resource id + * @param [in] num_cos number of classes of service at \a ca + * @param [in] requested table with class of service definitions + * @param [out] actual table with class of service definitions + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int os_mba_set_amd(const unsigned mba_id, + const unsigned num_cos, + const struct pqos_mba *requested, + struct pqos_mba *actual); + +/** * @brief OS interface to read MBA from \a mba_id * * @param [in] mba_id MBA resource id @@ -277,6 +292,24 @@ struct pqos_mba *mba_tab); /** + * @brief OS interface to read MBA from \a mba_id + * @NOTE: This function is specific to AMD + * + * @param [in] mba_id MBA resource id + * @param [in] max_num_cos maximum number of classes of service + * that can be accommodated at \a mba_tab + * @param [out] num_cos number of classes of service read into \a mba_tab + * @param [out] mba_tab table with read classes of service + * + * @return Operations status + * @retval PQOS_RETVAL_OK on success + */ +int os_mba_get_amd(const unsigned mba_id, + const unsigned max_num_cos, + unsigned *num_cos, + struct pqos_mba *mba_tab); + +/** * @brief OS interface to associate \a lcore * with given class of service * @@ -285,8 +318,7 @@ * * @return Operations status */ -int os_alloc_assoc_set(const unsigned lcore, - const unsigned class_id); +int os_alloc_assoc_set(const unsigned lcore, const unsigned class_id); /** * @brief OS interface to read association @@ -298,8 +330,7 @@ * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int os_alloc_assoc_get(const unsigned lcore, - unsigned *class_id); +int os_alloc_assoc_get(const unsigned lcore, unsigned *class_id); /** * @brief Retrieves task id's from resctrl task file for a given COS @@ -310,8 +341,7 @@ * @return Allocated task id array * @retval NULL on error */ -unsigned * -os_pid_get_pid_assoc(const unsigned class_id, unsigned *count); +unsigned *os_pid_get_pid_assoc(const unsigned class_id, unsigned *count); /** * @brief OS interface to associate \a task @@ -323,8 +353,7 @@ * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int os_alloc_assoc_set_pid(const pid_t task, - const unsigned class_id); +int os_alloc_assoc_set_pid(const pid_t task, const unsigned class_id); /** * @brief OS interface to read association @@ -336,8 +365,7 @@ * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int os_alloc_assoc_get_pid(const pid_t task, - unsigned *class_id); +int os_alloc_assoc_get_pid(const pid_t task, unsigned *class_id); #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/lib/os_cap.c intel-cmt-cat-4.0/lib/os_cap.c --- intel-cmt-cat-3.2/lib/os_cap.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/os_cap.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,9 +45,9 @@ #include "resctrl_alloc.h" #include "perf_monitoring.h" -#define PROC_CPUINFO "/proc/cpuinfo" +#define PROC_CPUINFO "/proc/cpuinfo" #define PROC_FILESYSTEMS "/proc/filesystems" -#define PROC_MOUNTS "/proc/mounts" +#define PROC_MOUNTS "/proc/mounts" static int mba_ctrl = -1; /**< mba ctrl support */ @@ -64,7 +64,9 @@ * @retval PQOS_RETVAL_OK success */ static int -detect_os_support(const char *fname, const char *str, int check_symlink, +detect_os_support(const char *fname, + const char *str, + int check_symlink, int *supported) { FILE *fd; @@ -74,7 +76,7 @@ return PQOS_RETVAL_PARAM; if (check_symlink) - fd = fopen_check_symlink(fname, "r"); + fd = pqos_fopen(fname, "r"); else fd = fopen(fname, "r"); @@ -118,7 +120,7 @@ ASSERT(fname != NULL); ASSERT(value != NULL); - fd = fopen_check_symlink(fname, "r"); + fd = pqos_fopen(fname, "r"); if (fd == NULL) return PQOS_RETVAL_ERROR; @@ -132,7 +134,7 @@ *value = strtoull(s, &endptr, base); if (!((*s != '\0' && *s != '\n') && - (*endptr == '\0' || *endptr == '\n'))) { + (*endptr == '\0' || *endptr == '\n'))) { LOG_ERROR("Error converting '%s' to unsigned number!\n", buf); return PQOS_RETVAL_ERROR; } @@ -216,7 +218,8 @@ /* Information not present in info dir */ if (access(path, F_OK) != 0) { LOG_DEBUG("Unable to obtain ways contention bit-mask, %s file " - "does not exist\n", path); + "does not exist\n", + path); *shareable_bits = 0; return PQOS_RETVAL_OK; } @@ -239,10 +242,9 @@ LOG_ERROR("Fatal error encountered in resctrl detection!\n"); return ret; } - LOG_INFO("%s\n", res_flag ? - "resctrl detected" : - "resctrl not detected. " - "Kernel version 4.10 or higher required"); + LOG_INFO("%s\n", res_flag ? "resctrl detected" + : "resctrl not detected. " + "Kernel version 4.10 or higher required"); if (res_flag == 0) { LOG_ERROR("OS interface selected but not supported\n"); @@ -252,7 +254,7 @@ /** * Mount resctrl with default parameters */ - if (access(RESCTRL_PATH"/cpus", F_OK) != 0) { + if (access(RESCTRL_PATH "/cpus", F_OK) != 0) { LOG_INFO("resctrl not mounted\n"); /** * Check if it is possible to enable MBA CTRL @@ -334,8 +336,8 @@ break; } - ret = detect_os_support(RESCTRL_PATH_INFO_L3_MON"/mon_features", - event_name, 1, supported); + ret = detect_os_support(RESCTRL_PATH_INFO_L3_MON "/mon_features", + event_name, 1, supported); if (scale != NULL) *scale = 1; @@ -343,7 +345,6 @@ return ret; } - /** * @brief Reads scale factor of perf monitoring event * @@ -367,31 +368,34 @@ ASSERT(event_name != NULL); /* read scale factor value */ - snprintf(path, sizeof(path) - 1, PERF_MON_PATH"/events/%s.scale", + snprintf(path, sizeof(path) - 1, PERF_MON_PATH "/events/%s.scale", event_name); - fd = fopen_check_symlink(path, "r"); + fd = pqos_fopen(path, "r"); if (fd == NULL) { LOG_ERROR("Failed to open %s perf monitoring event scale " - "file!\n", event_name); + "file!\n", + event_name); return PQOS_RETVAL_ERROR; } ret = fscanf(fd, "%10lf", &scale_factor); fclose(fd); if (ret < 1) { LOG_ERROR("Failed to read %s perf monitoring event scale " - "factor!\n", event_name); + "factor!\n", + event_name); return PQOS_RETVAL_ERROR; } /* read scale factor unit */ - snprintf(path, sizeof(path) - 1, PERF_MON_PATH"/events/%s.unit", + snprintf(path, sizeof(path) - 1, PERF_MON_PATH "/events/%s.unit", event_name); - fd = fopen_check_symlink(path, "r"); + fd = pqos_fopen(path, "r"); if (fd == NULL) { LOG_ERROR("Failed to open %s perf monitoring event unit " - "file!\n", event_name); + "file!\n", + event_name); return PQOS_RETVAL_ERROR; } @@ -467,7 +471,8 @@ break; } - snprintf(path, sizeof(path) - 1, PERF_MON_PATH"/events/%s", event_name); + snprintf(path, sizeof(path) - 1, PERF_MON_PATH "/events/%s", + event_name); if (stat(path, &st) != 0) return PQOS_RETVAL_OK; @@ -540,8 +545,7 @@ } int -os_cap_mon_discover(struct pqos_cap_mon **r_cap, - const struct pqos_cpuinfo *cpu) +os_cap_mon_discover(struct pqos_cap_mon **r_cap, const struct pqos_cpuinfo *cpu) { struct pqos_cap_mon *cap = NULL; int supported; @@ -550,12 +554,14 @@ unsigned i; enum pqos_mon_event events[] = { + /* clang-format off */ PQOS_MON_EVENT_L3_OCCUP, PQOS_MON_EVENT_LMEM_BW, PQOS_MON_EVENT_TMEM_BW, PQOS_MON_EVENT_RMEM_BW, PQOS_PERF_EVENT_LLC_MISS, PQOS_PERF_EVENT_IPC + /* clang-format on */ }; ret = detect_os_support(PROC_CPUINFO, "cqm", 0, &supported); @@ -567,14 +573,14 @@ if (!supported) return PQOS_RETVAL_RESOURCE; - if (access(RESCTRL_PATH_INFO_L3_MON"/num_rmids", F_OK) == 0) { - ret = readuint64(RESCTRL_PATH_INFO_L3_MON"/num_rmids", 10, + if (access(RESCTRL_PATH_INFO_L3_MON "/num_rmids", F_OK) == 0) { + ret = readuint64(RESCTRL_PATH_INFO_L3_MON "/num_rmids", 10, &num_rmids); if (ret != PQOS_RETVAL_OK) return ret; } - cap = (struct pqos_cap_mon *) malloc(sizeof(*cap)); + cap = (struct pqos_cap_mon *)malloc(sizeof(*cap)); if (cap == NULL) return PQOS_RETVAL_RESOURCE; memset(cap, 0, sizeof(*cap)); @@ -602,6 +608,7 @@ } monitor = &(mon->events[mon->num_events]); + memset(monitor, 0, sizeof(*monitor)); monitor->type = events[i]; monitor->max_rmid = num_rmids; monitor->scale_factor = scale; @@ -621,15 +628,15 @@ } int -os_cap_l3ca_discover(struct pqos_cap_l3ca **r_cap, - const struct pqos_cpuinfo *cpu) +os_cap_l3ca_discover(struct pqos_cap_l3ca *cap, const struct pqos_cpuinfo *cpu) { - struct pqos_cap_l3ca *cap = NULL; struct stat st; const char *info; int cdp_on; int ret = PQOS_RETVAL_OK; + ASSERT(cap != NULL); + if (stat(RESCTRL_PATH_INFO_L3, &st) == 0) { info = RESCTRL_PATH_INFO_L3; cdp_on = 0; @@ -640,11 +647,7 @@ } else return PQOS_RETVAL_RESOURCE; - cap = (struct pqos_cap_l3ca *)calloc(1, sizeof(*cap)); - if (cap == NULL) - return PQOS_RETVAL_RESOURCE; - - ASSERT(cap != NULL); + memset(cap, 0, sizeof(*cap)); cap->mem_size = sizeof(*cap); cap->cdp = cdp_on; cap->cdp_on = cdp_on; @@ -652,38 +655,32 @@ ret = get_num_closids(info, &cap->num_classes); if (ret != PQOS_RETVAL_OK) - goto os_cap_l3ca_discover_exit; + return ret; ret = get_num_ways(info, &cap->num_ways); if (ret != PQOS_RETVAL_OK) - goto os_cap_l3ca_discover_exit; + return ret; ret = get_shareable_bits(info, &cap->way_contention); if (ret != PQOS_RETVAL_OK) - goto os_cap_l3ca_discover_exit; + return ret; if (!cdp_on) ret = detect_os_support(PROC_CPUINFO, "cdp_l3", 0, &cap->cdp); - os_cap_l3ca_discover_exit: - if (ret == PQOS_RETVAL_OK) - *r_cap = cap; - else - free(cap); - return ret; } int -os_cap_l2ca_discover(struct pqos_cap_l2ca **r_cap, - const struct pqos_cpuinfo *cpu) +os_cap_l2ca_discover(struct pqos_cap_l2ca *cap, const struct pqos_cpuinfo *cpu) { - struct pqos_cap_l2ca *cap = NULL; struct stat st; const char *info; int cdp_on; int ret = PQOS_RETVAL_OK; + ASSERT(cap != NULL); + if (stat(RESCTRL_PATH_INFO_L2, &st) == 0) { info = RESCTRL_PATH_INFO_L2; cdp_on = 0; @@ -694,11 +691,7 @@ } else return PQOS_RETVAL_RESOURCE; - cap = (struct pqos_cap_l2ca *)calloc(1, sizeof(*cap)); - if (cap == NULL) - return PQOS_RETVAL_RESOURCE; - - ASSERT(cap != NULL); + memset(cap, 0, sizeof(*cap)); cap->mem_size = sizeof(*cap); cap->cdp = cdp_on; cap->cdp_on = cdp_on; @@ -706,25 +699,19 @@ ret = get_num_closids(info, &cap->num_classes); if (ret != PQOS_RETVAL_OK) - goto os_cap_l2ca_discover_exit; + return ret; ret = get_num_ways(info, &cap->num_ways); if (ret != PQOS_RETVAL_OK) - goto os_cap_l2ca_discover_exit; + return ret; ret = get_shareable_bits(info, &cap->way_contention); if (ret != PQOS_RETVAL_OK) - goto os_cap_l2ca_discover_exit; + return ret; if (!cdp_on) ret = detect_os_support(PROC_CPUINFO, "cdp_l2", 0, &cap->cdp); - os_cap_l2ca_discover_exit: - if (ret == PQOS_RETVAL_OK) - *r_cap = cap; - else - free(cap); - return ret; } @@ -747,7 +734,7 @@ return PQOS_RETVAL_OK; } - if (access(RESCTRL_PATH"/cpus", F_OK) != 0) + if (access(RESCTRL_PATH "/cpus", F_OK) != 0) *enabled = 0; /* check mount flags */ @@ -762,20 +749,20 @@ unsigned grp; unsigned count = 0; unsigned i; - unsigned *mba_ids, mba_id_num; + unsigned *mba_ids, mba_id_num; struct resctrl_schemata *schmt; ret = resctrl_alloc_get_grps_num(cap, &count); if (ret != PQOS_RETVAL_OK) return ret; - mba_ids = pqos_cpu_get_mba_ids(cpu, &mba_id_num); - if (mba_ids == NULL) + mba_ids = pqos_cpu_get_mba_ids(cpu, &mba_id_num); + if (mba_ids == NULL) return PQOS_RETVAL_ERROR; schmt = resctrl_schemata_alloc(cap, cpu); if (schmt == NULL) { - free(mba_ids); + free(mba_ids); return PQOS_RETVAL_ERROR; } @@ -784,12 +771,11 @@ if (ret != PQOS_RETVAL_OK) continue; - for (i = 0; i < mba_id_num; i++) { + for (i = 0; i < mba_id_num; i++) { struct pqos_mba mba; - ret = resctrl_schemata_mba_get(schmt, - mba_ids[i], - &mba); + ret = resctrl_schemata_mba_get( + schmt, mba_ids[i], &mba); if (ret == PQOS_RETVAL_OK && mba.mb_max > 100) { *enabled = 1; break; @@ -798,7 +784,7 @@ } resctrl_schemata_free(schmt); - free(mba_ids); + free(mba_ids); } /* get free COS and try to write value above 100 */ @@ -845,7 +831,7 @@ resctrl_schemata_free(schmt); } - ctrl_support: +ctrl_support: if (*supported != -1) goto ctrl_exit; @@ -864,7 +850,7 @@ *supported = 0; } - ctrl_exit: +ctrl_exit: if (*supported == 0) *enabled = 0; @@ -879,65 +865,54 @@ } int -os_cap_mba_discover(struct pqos_cap_mba **r_cap, - const struct pqos_cpuinfo *cpu) +os_cap_mba_discover(struct pqos_cap_mba *cap, const struct pqos_cpuinfo *cpu) { - struct pqos_cap_mba *cap = NULL; struct stat st; uint64_t val; const char *info = RESCTRL_PATH_INFO_MB; int ret = PQOS_RETVAL_OK; UNUSED_PARAM(cpu); + ASSERT(cap != NULL); if (stat(RESCTRL_PATH_INFO_MB, &st) != 0) return PQOS_RETVAL_RESOURCE; - cap = (struct pqos_cap_mba *)calloc(1, sizeof(*cap)); - if (cap == NULL) - return PQOS_RETVAL_RESOURCE; - - ASSERT(cap != NULL); + memset(cap, 0, sizeof(*cap)); cap->mem_size = sizeof(*cap); cap->ctrl = -1; cap->ctrl_on = -1; ret = get_num_closids(info, &cap->num_classes); if (ret != PQOS_RETVAL_OK) - goto os_cap_mba_discover_exit; + return ret; /* Detect MBA CTRL status */ ret = detect_os_support(PROC_MOUNTS, "mba_MBps", 0, &(cap->ctrl_on)); if (ret != PQOS_RETVAL_OK) - goto os_cap_mba_discover_exit; + return ret; if (cap->ctrl_on == 1) cap->ctrl = 1; else cap->ctrl = mba_ctrl; - ret = readuint64(RESCTRL_PATH_INFO_MB"/min_bandwidth", 10, &val); + ret = readuint64(RESCTRL_PATH_INFO_MB "/min_bandwidth", 10, &val); if (ret != PQOS_RETVAL_OK) - goto os_cap_mba_discover_exit; + return ret; else cap->throttle_max = 100 - val; - ret = readuint64(RESCTRL_PATH_INFO_MB"/bandwidth_gran", 10, &val); + ret = readuint64(RESCTRL_PATH_INFO_MB "/bandwidth_gran", 10, &val); if (ret != PQOS_RETVAL_OK) - goto os_cap_mba_discover_exit; + return ret; else cap->throttle_step = val; - ret = readuint64(RESCTRL_PATH_INFO_MB"/delay_linear", 10, &val); + ret = readuint64(RESCTRL_PATH_INFO_MB "/delay_linear", 10, &val); if (ret != PQOS_RETVAL_OK) - goto os_cap_mba_discover_exit; + return ret; else cap->is_linear = (val == 1); - os_cap_mba_discover_exit: - if (ret == PQOS_RETVAL_OK) - *r_cap = cap; - else - free(cap); - return ret; } diff -Nru intel-cmt-cat-3.2/lib/os_cap.h intel-cmt-cat-4.0/lib/os_cap.h --- intel-cmt-cat-3.2/lib/os_cap.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/os_cap.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,37 +80,37 @@ /** * @brief Discovers OS support of L3 CAT * - * @param r_cap place to store CAT capabilities structure + * @param cap place to store CAT capabilities * @param cpu detected cpu topology * * @return Operation status * @retval PQOS_RETVAL_OK success */ -int os_cap_l3ca_discover(struct pqos_cap_l3ca **r_cap, +int os_cap_l3ca_discover(struct pqos_cap_l3ca *cap, const struct pqos_cpuinfo *cpu); /** * @brief Discovers OS support of L2 CAT * - * @param r_cap place to store CAT capabilities structure + * @param cap place to store CAT capabilities * @param cpu detected cpu topology * * @return Operation status * @retval PQOS_RETVAL_OK success */ -int os_cap_l2ca_discover(struct pqos_cap_l2ca **r_cap, +int os_cap_l2ca_discover(struct pqos_cap_l2ca *cap, const struct pqos_cpuinfo *cpu); /** * @brief Discovers OS support of MBA * - * @param r_cap place to store MBA capabilities structure + * @param cap place to store MBA capabilities * @param cpu detected cpu topology * * @return Operation status * @retval PQOS_RETVAL_OK success */ -int os_cap_mba_discover(struct pqos_cap_mba **r_cap, +int os_cap_mba_discover(struct pqos_cap_mba *cap, const struct pqos_cpuinfo *cpu); #ifdef __cplusplus diff -Nru intel-cmt-cat-3.2/lib/os_monitoring.c intel-cmt-cat-4.0/lib/os_monitoring.c --- intel-cmt-cat-3.2/lib/os_monitoring.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/os_monitoring.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,13 +34,14 @@ #include #include -#include /**< pid_t */ -#include /**< scandir() */ +#include /**< pid_t */ +#include /**< scandir() */ #include "pqos.h" #include "cap.h" #include "log.h" #include "types.h" +#include "monitoring.h" #include "os_monitoring.h" #include "perf_monitoring.h" #include "resctrl.h" @@ -55,12 +56,12 @@ /** List of non virtual events */ const enum pqos_mon_event os_mon_event[] = { - PQOS_MON_EVENT_L3_OCCUP, - PQOS_MON_EVENT_LMEM_BW, - PQOS_MON_EVENT_TMEM_BW, - PQOS_PERF_EVENT_LLC_MISS, - (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES, - (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS}; + PQOS_MON_EVENT_L3_OCCUP, + PQOS_MON_EVENT_LMEM_BW, + PQOS_MON_EVENT_TMEM_BW, + PQOS_PERF_EVENT_LLC_MISS, + (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES, + (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS}; /** * @brief Filter directory filenames @@ -77,7 +78,7 @@ static int filter(const struct dirent *dir) { - return (dir->d_name[0] == '.') ? 0 : 1; + return (dir->d_name[0] == '.') ? 0 : 1; } /** @@ -104,50 +105,52 @@ /** * Stop perf event */ - if (group->perf_event & evt) { + if (group->intl->perf.event & evt) { ret = perf_mon_stop(group, evt); if (ret == PQOS_RETVAL_OK) stopped_evts |= evt; } } - if (group->resctrl_event) { + if (group->intl->resctrl.event) { ret = resctrl_lock_exclusive(); if (ret != PQOS_RETVAL_OK) goto stop_event_error; ret = resctrl_mon_stop(group); if (ret == PQOS_RETVAL_OK) - stopped_evts |= group->resctrl_event; + stopped_evts |= group->intl->resctrl.event; resctrl_lock_release(); } - stop_event_error: +stop_event_error: if ((stopped_evts & PQOS_MON_EVENT_LMEM_BW) && - (stopped_evts & PQOS_MON_EVENT_TMEM_BW)) + (stopped_evts & PQOS_MON_EVENT_TMEM_BW)) stopped_evts |= (enum pqos_mon_event)PQOS_MON_EVENT_RMEM_BW; if ((stopped_evts & PQOS_PERF_EVENT_CYCLES) && - (stopped_evts & PQOS_PERF_EVENT_INSTRUCTIONS)) + (stopped_evts & PQOS_PERF_EVENT_INSTRUCTIONS)) stopped_evts |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC; - if (group->perf != NULL) { - free(group->perf); - group->perf = NULL; + if (group->intl->perf.ctx != NULL) { + free(group->intl->perf.ctx); + group->intl->perf.ctx = NULL; } - if ((group->perf_event & stopped_evts) != group->perf_event) { + if ((group->intl->perf.event & stopped_evts) != + group->intl->perf.event) { LOG_ERROR("Failed to stop all perf events\n"); return PQOS_RETVAL_ERROR; } - group->perf_event = (enum pqos_mon_event)0; + group->intl->perf.event = (enum pqos_mon_event)0; - if ((group->resctrl_event & stopped_evts) != group->resctrl_event) { + if ((group->intl->resctrl.event & stopped_evts) != + group->intl->resctrl.event) { LOG_ERROR("Failed to stop resctrl events\n"); return PQOS_RETVAL_ERROR; } - group->resctrl_event = (enum pqos_mon_event)0; + group->intl->resctrl.event = (enum pqos_mon_event)0; return PQOS_RETVAL_OK; } @@ -179,19 +182,20 @@ return PQOS_RETVAL_ERROR; events = group->event; - group->perf_event = (enum pqos_mon_event)0; - group->perf = malloc(sizeof(group->perf[0]) * num_ctrs); - if (group->perf == NULL) { + group->intl->perf.event = (enum pqos_mon_event)0; + group->intl->perf.ctx = + malloc(sizeof(group->intl->perf.ctx[0]) * num_ctrs); + if (group->intl->perf.ctx == NULL) { LOG_ERROR("Memory allocation failed\n"); return PQOS_RETVAL_ERROR; } if (events & PQOS_MON_EVENT_RMEM_BW) events |= (enum pqos_mon_event)(PQOS_MON_EVENT_LMEM_BW | - PQOS_MON_EVENT_TMEM_BW); + PQOS_MON_EVENT_TMEM_BW); if (events & PQOS_PERF_EVENT_IPC) events |= (enum pqos_mon_event)(PQOS_PERF_EVENT_CYCLES | - PQOS_PERF_EVENT_INSTRUCTIONS); + PQOS_PERF_EVENT_INSTRUCTIONS); /** * Determine selected events and Perf counters @@ -204,12 +208,12 @@ ret = perf_mon_start(group, evt); if (ret != PQOS_RETVAL_OK) goto start_event_error; - group->perf_event |= evt; + group->intl->perf.event |= evt; continue; } if (resctrl_mon_is_event_supported(evt)) { - group->resctrl_event |= evt; + group->intl->resctrl.event |= evt; continue; } @@ -220,9 +224,9 @@ goto start_event_error; } } - started_evts |= group->perf_event; + started_evts |= group->intl->perf.event; - if (group->resctrl_event != 0) { + if (group->intl->resctrl.event != 0) { ret = resctrl_lock_exclusive(); if (ret != PQOS_RETVAL_OK) goto start_event_error; @@ -232,13 +236,13 @@ if (ret != PQOS_RETVAL_OK) goto start_event_error; } - started_evts |= group->resctrl_event; + started_evts |= group->intl->resctrl.event; /** * All events required by RMEM has been started */ if ((started_evts & PQOS_MON_EVENT_LMEM_BW) && - (started_evts & PQOS_MON_EVENT_TMEM_BW)) { + (started_evts & PQOS_MON_EVENT_TMEM_BW)) { group->values.mbm_remote = 0; started_evts |= (enum pqos_mon_event)PQOS_MON_EVENT_RMEM_BW; } @@ -246,19 +250,19 @@ * All events required by IPC has been started */ if ((started_evts & PQOS_PERF_EVENT_CYCLES) && - (started_evts & PQOS_PERF_EVENT_INSTRUCTIONS)) { + (started_evts & PQOS_PERF_EVENT_INSTRUCTIONS)) { group->values.ipc = 0; started_evts |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC; } - start_event_error: +start_event_error: /* Check if all selected events were started */ if ((group->event & started_evts) != group->event) { stop_events(group); LOG_ERROR("Failed to start all selected " "OS monitoring events\n"); - free(group->perf); - group->perf = NULL; + free(group->intl->perf.ctx); + group->intl->perf.ctx = NULL; } return ret; } @@ -278,7 +282,7 @@ unsigned i; int ret = PQOS_RETVAL_OK; - if (group->resctrl_event != 0) { + if (group->intl->resctrl.event != 0) { ret = resctrl_lock_shared(); if (ret != PQOS_RETVAL_OK) return ret; @@ -290,7 +294,7 @@ /** * poll perf event */ - if (group->perf_event & evt) { + if (group->intl->perf.event & evt) { ret = perf_mon_poll(group, evt); if (ret != PQOS_RETVAL_OK) goto poll_events_exit; @@ -299,7 +303,7 @@ /** * poll resctrl event */ - if (group->resctrl_event & evt) { + if (group->intl->resctrl.event & evt) { ret = resctrl_mon_poll(group, evt); if (ret != PQOS_RETVAL_OK) goto poll_events_exit; @@ -314,20 +318,20 @@ if (group->values.mbm_total_delta > group->values.mbm_local_delta) group->values.mbm_remote_delta = - group->values.mbm_total_delta - - group->values.mbm_local_delta; + group->values.mbm_total_delta - + group->values.mbm_local_delta; } if (group->event & PQOS_PERF_EVENT_IPC) { if (group->values.ipc_unhalted_delta > 0) group->values.ipc = - (double)group->values.ipc_retired_delta / - (double)group->values.ipc_unhalted_delta; + (double)group->values.ipc_retired_delta / + (double)group->values.ipc_unhalted_delta; else group->values.ipc = 0; } - poll_events_exit: - if (group->resctrl_event != 0) +poll_events_exit: + if (group->intl->resctrl.event != 0) resctrl_lock_release(); return ret; @@ -341,8 +345,8 @@ ASSERT(cpu != NULL); ASSERT(cap != NULL); - if (cpu == NULL || cap == NULL) - return PQOS_RETVAL_PARAM; + if (cpu == NULL || cap == NULL) + return PQOS_RETVAL_PARAM; ret = perf_mon_init(cpu, cap); if (ret == PQOS_RETVAL_RESOURCE) @@ -351,7 +355,7 @@ if (ret != PQOS_RETVAL_OK) return ret; - m_cpu = cpu; + m_cpu = cpu; return ret; } @@ -424,7 +428,7 @@ */ for (i = 0; i < (sizeof(event) * 8); i++) { const enum pqos_mon_event evt_mask = - (enum pqos_mon_event)(1U << i); + (enum pqos_mon_event)(1U << i); const struct pqos_monitor *ptr = NULL; if (!(evt_mask & event)) @@ -449,10 +453,9 @@ /** * Fill in the monitoring group structure */ - memset(group, 0, sizeof(*group)); group->event = event; group->context = context; - group->cores = (unsigned *) malloc(sizeof(group->cores[0]) * num_cores); + group->cores = (unsigned *)malloc(sizeof(group->cores[0]) * num_cores); if (group->cores == NULL) return PQOS_RETVAL_RESOURCE; @@ -558,8 +561,8 @@ ret = tid_add(pid, tid_nr, tid_map); else for (i = 0; i < num_tasks; i++) { - ret = tid_add((pid_t)atoi(namelist[i]->d_name), - tid_nr, tid_map); + ret = tid_add((pid_t)atoi(namelist[i]->d_name), tid_nr, + tid_map); if (ret != PQOS_RETVAL_OK) break; } @@ -634,8 +637,7 @@ goto os_mon_start_pids_exit; } - memset(group, 0, sizeof(*group)); - group->pids = (pid_t *) malloc(sizeof(pid_t) * num_pids); + group->pids = (pid_t *)malloc(sizeof(pid_t) * num_pids); if (group->pids == NULL) { ret = PQOS_RETVAL_RESOURCE; goto os_mon_start_pids_exit; @@ -652,7 +654,7 @@ ret = start_events(group); - os_mon_start_pids_exit: +os_mon_start_pids_exit: if (ret != PQOS_RETVAL_OK && tid_map != NULL) free(tid_map); @@ -725,9 +727,14 @@ added.tid_map = tid_map; added.event = group->event; added.num_pids = num_pids; - if (group->resctrl_mon_group != NULL) { - added.resctrl_mon_group = strdup(group->resctrl_mon_group); - if (added.resctrl_mon_group == NULL) { + added.intl = malloc(sizeof(*added.intl)); + if (added.intl == NULL) + goto os_mon_add_pids_exit; + memset(added.intl, 0, sizeof(*added.intl)); + if (group->intl->resctrl.mon_group != NULL) { + added.intl->resctrl.mon_group = + strdup(group->intl->resctrl.mon_group); + if (added.intl->resctrl.mon_group == NULL) { ret = PQOS_RETVAL_RESOURCE; goto os_mon_add_pids_exit; } @@ -740,24 +747,25 @@ /** * Update mon group */ - ptr = realloc(group->tid_map, - sizeof(group->tid_map[0]) * (group->tid_nr + added.tid_nr)); + ptr = realloc(group->tid_map, sizeof(group->tid_map[0]) * + (group->tid_nr + added.tid_nr)); if (ptr == NULL) { ret = PQOS_RETVAL_RESOURCE; goto os_mon_add_pids_exit; } group->tid_map = ptr; - ctx = realloc(group->perf, - sizeof(group->perf[0]) * (group->tid_nr + added.tid_nr)); + ctx = + realloc(group->intl->perf.ctx, sizeof(group->intl->perf.ctx[0]) * + (group->tid_nr + added.tid_nr)); if (ctx == NULL) { ret = PQOS_RETVAL_RESOURCE; goto os_mon_add_pids_exit; } - group->perf = ctx; + group->intl->perf.ctx = ctx; ptr = realloc(group->pids, - sizeof(group->pids[0]) * (group->num_pids + num_pids)); + sizeof(group->pids[0]) * (group->num_pids + num_pids)); if (ptr == NULL) { ret = PQOS_RETVAL_RESOURCE; goto os_mon_add_pids_exit; @@ -766,7 +774,7 @@ for (i = 0; i < added.tid_nr; i++) { group->tid_map[group->tid_nr] = added.tid_map[i]; - group->perf[group->tid_nr] = added.perf[i]; + group->intl->perf.ctx[group->tid_nr] = added.intl->perf.ctx[i]; group->tid_nr++; } for (i = 0; i < num_pids; i++) { @@ -774,17 +782,20 @@ group->num_pids++; } - os_mon_add_pids_exit: - if (added.resctrl_mon_group != NULL) { - free(added.resctrl_mon_group); - added.resctrl_mon_group = NULL; +os_mon_add_pids_exit: + if (added.intl != NULL && added.intl->resctrl.mon_group != NULL) { + free(added.intl->resctrl.mon_group); + added.intl->resctrl.mon_group = NULL; } if (ret == PQOS_RETVAL_RESOURCE) { LOG_ERROR("Memory allocation error!\n"); stop_events(&added); } - if (added.perf != NULL) - free(added.perf); + if (added.intl != NULL) { + if (added.intl->perf.ctx != NULL) + free(added.intl->perf.ctx); + free(added.intl); + } if (tid_map != NULL) free(tid_map); return ret; @@ -807,6 +818,8 @@ ASSERT(pids != NULL); ASSERT(group != NULL); + memset(&remove, 0, sizeof(remove)); + /** * Find TID's for not removed tasks */ @@ -824,19 +837,22 @@ goto os_mon_remove_pids_exit; } - memset(&remove, 0, sizeof(remove)); - remove.perf_event = group->perf_event; - remove.resctrl_event = group->resctrl_event; + remove.intl = + (struct pqos_mon_data_internal *)malloc(sizeof(*remove.intl)); + if (remove.intl == NULL) + goto os_mon_remove_pids_exit; + memset(remove.intl, 0, sizeof(*remove.intl)); + remove.intl->perf.event = group->intl->perf.event; + remove.intl->resctrl.event = group->intl->resctrl.event; remove.pids = NULL; remove.num_pids = num_pids; remove.tid_map = malloc(sizeof(remove.tid_map[0]) * group->tid_nr); if (remove.tid_map == NULL) goto os_mon_remove_pids_exit; - remove.perf = malloc(sizeof(remove.perf[0]) * group->tid_nr); - if (remove.perf == NULL) { - free(remove.tid_map); + remove.intl->perf.ctx = + malloc(sizeof(remove.intl->perf.ctx[0]) * group->tid_nr); + if (remove.intl->perf.ctx == NULL) goto os_mon_remove_pids_exit; - } /* Add tid's for removal */ for (i = 0; i < group->tid_nr; i++) { @@ -845,13 +861,11 @@ continue; remove.tid_map[remove.tid_nr] = group->tid_map[i]; - remove.perf[remove.tid_nr] = group->perf[i]; + remove.intl->perf.ctx[remove.tid_nr] = group->intl->perf.ctx[i]; remove.tid_nr++; } ret = stop_events(&remove); - free(remove.perf); - free(remove.tid_map); if (ret != PQOS_RETVAL_OK) goto os_mon_remove_pids_exit; @@ -867,13 +881,14 @@ } group->tid_map[i - removed] = group->tid_map[i]; - group->perf[i - removed] = group->perf[i]; + group->intl->perf.ctx[i - removed] = group->intl->perf.ctx[i]; } group->tid_nr -= removed; - group->tid_map = realloc(group->tid_map, - sizeof(group->tid_map[0]) * group->tid_nr); - group->perf = realloc(group->perf, - sizeof(group->perf[0]) * group->tid_nr); + group->tid_map = + realloc(group->tid_map, sizeof(group->tid_map[0]) * group->tid_nr); + group->intl->perf.ctx = + realloc(group->intl->perf.ctx, + sizeof(group->intl->perf.ctx[0]) * group->tid_nr); removed = 0; for (i = 0; i < group->num_pids; i++) { if (tid_exists(group->pids[i], num_pids, pids)) { @@ -884,18 +899,24 @@ group->pids[i - removed] = group->pids[i]; } group->num_pids -= removed; - group->pids = realloc(group->pids, - sizeof(group->pids[0]) * group->num_pids); + group->pids = + realloc(group->pids, sizeof(group->pids[0]) * group->num_pids); - os_mon_remove_pids_exit: +os_mon_remove_pids_exit: + if (remove.tid_map != NULL) + free(remove.tid_map); + if (remove.intl != NULL) { + if (remove.intl->perf.ctx) + free(remove.intl->perf.ctx); + free(remove.intl); + } if (keep_tid_map != NULL) free(keep_tid_map); return ret; } int -os_mon_poll(struct pqos_mon_data **groups, - const unsigned num_groups) +os_mon_poll(struct pqos_mon_data **groups, const unsigned num_groups) { unsigned i = 0; @@ -907,7 +928,8 @@ if (ret != PQOS_RETVAL_OK) LOG_WARN("Failed to poll event on " - "group number %u\n", i); + "group number %u\n", + i); } return PQOS_RETVAL_OK; diff -Nru intel-cmt-cat-3.2/lib/os_monitoring.h intel-cmt-cat-4.0/lib/os_monitoring.h --- intel-cmt-cat-3.2/lib/os_monitoring.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/os_monitoring.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,8 +80,7 @@ * @retval PQOS_RETVAL_OK on success * @retval PQOS_RETVAL_ERROR if error occurs */ -int -os_mon_stop(struct pqos_mon_data *group); +int os_mon_stop(struct pqos_mon_data *group); /** * @brief OS interface to start resource monitoring on selected @@ -118,8 +117,7 @@ * @return Operations status * @retval PQOS_RETVAL_OK on success */ -int os_mon_poll(struct pqos_mon_data **groups, - const unsigned num_groups); +int os_mon_poll(struct pqos_mon_data **groups, const unsigned num_groups); /** * @brief OS interface to start monitoring of selected group of \a pids diff -Nru intel-cmt-cat-3.2/lib/perf.c intel-cmt-cat-4.0/lib/perf.c --- intel-cmt-cat-3.2/lib/perf.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perf.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2015-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2015-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,12 +53,14 @@ * @retval negative number on error */ static inline int -perf_event_open(struct perf_event_attr *attr, pid_t pid, - int cpu, int group_fd, unsigned long flags) +perf_event_open(struct perf_event_attr *attr, + pid_t pid, + int cpu, + int group_fd, + unsigned long flags) { attr->size = sizeof(*attr); - return syscall(__NR_perf_event_open, attr, - pid, cpu, group_fd, flags); + return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); } int @@ -149,5 +151,5 @@ return PQOS_RETVAL_ERROR; } - return PQOS_RETVAL_OK; + return PQOS_RETVAL_OK; } diff -Nru intel-cmt-cat-3.2/lib/perf.h intel-cmt-cat-4.0/lib/perf.h --- intel-cmt-cat-3.2/lib/perf.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perf.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2015-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2015-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,13 +56,12 @@ * @retval positive number on success * @retval negative number on error */ -int -perf_setup_counter(struct perf_event_attr *attr, - const pid_t pid, - const int cpu, - const int group_fd, - const unsigned long flags, - int *counter_fd); +int perf_setup_counter(struct perf_event_attr *attr, + const pid_t pid, + const int cpu, + const int group_fd, + const unsigned long flags, + int *counter_fd); /** * @brief Function to shutdown a perf event counter @@ -72,8 +71,7 @@ * @return Operational status * @retval PQOS_RETVAL_OK on success */ -int -perf_shutdown_counter(int counter_fd); +int perf_shutdown_counter(int counter_fd); /** * @brief Function to start a perf counter @@ -83,8 +81,7 @@ * @return Operational status * @retval PQOS_RETVAL_OK on success */ -int -perf_start_counter(int counter_fd); +int perf_start_counter(int counter_fd); /** * @brief Function to stop a perf counter @@ -94,8 +91,7 @@ * @return Operational status * @retval PQOS_RETVAL_OK on success */ -int -perf_stop_counter(int counter_fd); +int perf_stop_counter(int counter_fd); /** * @brief Function to read a perf counter @@ -106,8 +102,7 @@ * @return Operational status * @retval PQOS_RETVAL_OK on success */ -int -perf_read_counter(int counter_fd, uint64_t *value); +int perf_read_counter(int counter_fd, uint64_t *value); #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/lib/perf_monitoring.c intel-cmt-cat-4.0/lib/perf_monitoring.c --- intel-cmt-cat-3.2/lib/perf_monitoring.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perf_monitoring.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,27 +34,29 @@ #include #include -#include /**< scandir() */ +#include /**< scandir() */ #include +#include #include "pqos.h" #include "common.h" #include "perf.h" #include "log.h" #include "types.h" +#include "monitoring.h" #include "perf_monitoring.h" /** * Event indexes in table of supported events */ -#define OS_MON_EVT_IDX_LLC 0 -#define OS_MON_EVT_IDX_LMBM 1 -#define OS_MON_EVT_IDX_TMBM 2 -#define OS_MON_EVT_IDX_RMBM 3 -#define OS_MON_EVT_IDX_INST 4 -#define OS_MON_EVT_IDX_CYC 5 -#define OS_MON_EVT_IDX_IPC 6 -#define OS_MON_EVT_IDX_LLC_MISS 7 +#define OS_MON_EVT_IDX_LLC 0 +#define OS_MON_EVT_IDX_LMBM 1 +#define OS_MON_EVT_IDX_TMBM 2 +#define OS_MON_EVT_IDX_RMBM 3 +#define OS_MON_EVT_IDX_INST 4 +#define OS_MON_EVT_IDX_CYC 5 +#define OS_MON_EVT_IDX_IPC 6 +#define OS_MON_EVT_IDX_LLC_MISS 7 /** * --------------------------------------- @@ -66,6 +68,9 @@ /** * Paths to RDT perf event info */ +#ifndef PERF_MON_SUPPORT +#define PERF_MON_SUPPORT "/proc/sys/kernel/perf_event_paranoid" +#endif static const char *perf_events = "events/"; static const char *perf_type = "type"; @@ -92,42 +97,42 @@ double scale; struct perf_event_attr attrs; } events_tab[] = { - { .name = "llc_occupancy", - .desc = "LLC Occupancy", - .event = PQOS_MON_EVENT_L3_OCCUP, - .supported = 0, - .scale = 1 }, - { .name = "local_bytes", - .desc = "Local Memory B/W", - .event = PQOS_MON_EVENT_LMEM_BW, - .supported = 0, - .scale = 1 }, - { .name = "total_bytes", - .desc = "Total Memory B/W", - .event = PQOS_MON_EVENT_TMEM_BW, - .supported = 0, - .scale = 1 }, - { .name = "", - .desc = "Remote Memory B/W", - .event = PQOS_MON_EVENT_RMEM_BW, - .supported = 0, - .scale = 1 }, - { .name = "", - .desc = "Retired CPU Instructions", - .event = (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS, - .supported = 1 }, /**< assumed support */ - { .name = "", - .desc = "Unhalted CPU Cycles", - .event = (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES, - .supported = 1 }, /**< assumed support */ - { .name = "", - .desc = "Instructions/Cycle", - .event = PQOS_PERF_EVENT_IPC, - .supported = 1 }, /**< assumed support */ - { .name = "", - .desc = "LLC Misses", - .event = PQOS_PERF_EVENT_LLC_MISS, - .supported = 1 }, /**< assumed support */ + {.name = "llc_occupancy", + .desc = "LLC Occupancy", + .event = PQOS_MON_EVENT_L3_OCCUP, + .supported = 0, + .scale = 1}, + {.name = "local_bytes", + .desc = "Local Memory B/W", + .event = PQOS_MON_EVENT_LMEM_BW, + .supported = 0, + .scale = 1}, + {.name = "total_bytes", + .desc = "Total Memory B/W", + .event = PQOS_MON_EVENT_TMEM_BW, + .supported = 0, + .scale = 1}, + {.name = "", + .desc = "Remote Memory B/W", + .event = PQOS_MON_EVENT_RMEM_BW, + .supported = 0, + .scale = 1}, + {.name = "", + .desc = "Retired CPU Instructions", + .event = (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS, + .supported = 0}, + {.name = "", + .desc = "Unhalted CPU Cycles", + .event = (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES, + .supported = 0}, + {.name = "", + .desc = "Instructions/Cycle", + .event = PQOS_PERF_EVENT_IPC, + .supported = 0}, + {.name = "", + .desc = "LLC Misses", + .event = PQOS_PERF_EVENT_LLC_MISS, + .supported = 0}, }; /** @@ -168,9 +173,9 @@ return &events_tab[OS_MON_EVT_IDX_TMBM]; case PQOS_MON_EVENT_RMEM_BW: return &events_tab[OS_MON_EVT_IDX_RMBM]; - case (enum pqos_mon_event) PQOS_PERF_EVENT_INSTRUCTIONS: + case (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS: return &events_tab[OS_MON_EVT_IDX_INST]; - case (enum pqos_mon_event) PQOS_PERF_EVENT_CYCLES: + case (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES: return &events_tab[OS_MON_EVT_IDX_CYC]; case PQOS_PERF_EVENT_IPC: return &events_tab[OS_MON_EVT_IDX_IPC]; @@ -195,12 +200,9 @@ char file[64], evt[8]; snprintf(file, sizeof(file) - 1, "%s%s", PERF_MON_PATH, perf_type); - fd = fopen_check_symlink(file, "r"); - if (fd == NULL) { - LOG_INFO("Perf monitoring not supported. " - "Kernel version 4.6 or higher required.\n"); + fd = pqos_fopen(file, "r"); + if (fd == NULL) return PQOS_RETVAL_RESOURCE; - } if (fgets(evt, sizeof(evt), fd) == NULL) { LOG_ERROR("Failed to read perf monitoring type!\n"); fclose(fd); @@ -208,7 +210,7 @@ } fclose(fd); - os_mon_type = (int) strtol(evt, NULL, 0); + os_mon_type = (int)strtol(evt, NULL, 0); if (os_mon_type == 0) { LOG_ERROR("Failed to convert perf monitoring type!\n"); return PQOS_RETVAL_ERROR; @@ -242,19 +244,18 @@ /* Set LLC misses event attributes */ events_tab[OS_MON_EVT_IDX_LLC_MISS].attrs = attr; events_tab[OS_MON_EVT_IDX_LLC_MISS].attrs.config = - PERF_COUNT_HW_CACHE_MISSES; + PERF_COUNT_HW_CACHE_MISSES; *events |= (enum pqos_mon_event)PQOS_PERF_EVENT_LLC_MISS; /* Set retired instructions event attributes */ events_tab[OS_MON_EVT_IDX_INST].attrs = attr; events_tab[OS_MON_EVT_IDX_INST].attrs.config = - PERF_COUNT_HW_INSTRUCTIONS; + PERF_COUNT_HW_INSTRUCTIONS; *events |= (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS; /* Set unhalted cycles event attributes */ events_tab[OS_MON_EVT_IDX_CYC].attrs = attr; - events_tab[OS_MON_EVT_IDX_CYC].attrs.config = - PERF_COUNT_HW_CPU_CYCLES; + events_tab[OS_MON_EVT_IDX_CYC].attrs.config = PERF_COUNT_HW_CPU_CYCLES; *events |= (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES; *events |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC; @@ -287,7 +288,7 @@ */ snprintf(file, sizeof(file) - 1, "%s%s%s", PERF_MON_PATH, perf_events, fname); - fd = fopen_check_symlink(file, "r"); + fd = pqos_fopen(file, "r"); if (fd == NULL) { LOG_ERROR("Failed to open %s!\n", file); return PQOS_RETVAL_ERROR; @@ -310,9 +311,9 @@ /** * Read scale factor from file system */ - snprintf(file, sizeof(file) - 1, "%s%s%s.scale", - PERF_MON_PATH, perf_events, fname); - fd = fopen_check_symlink(file, "r"); + snprintf(file, sizeof(file) - 1, "%s%s%s.scale", PERF_MON_PATH, + perf_events, fname); + fd = pqos_fopen(file, "r"); if (fd == NULL) { LOG_ERROR("Failed to open OS monitoring event scale file!\n"); return PQOS_RETVAL_ERROR; @@ -372,12 +373,12 @@ * so, set up event attributes */ for (j = 0; j < DIM(events_tab); j++) { - if ((strcmp(events_tab[j].name, - namelist[i]->d_name)) != 0) + if ((strcmp(events_tab[j].name, namelist[i]->d_name)) != + 0) continue; - if (set_rdt_event_attrs(j, namelist[i]->d_name) - != PQOS_RETVAL_OK) { + if (set_rdt_event_attrs(j, namelist[i]->d_name) != + PQOS_RETVAL_OK) { ret = PQOS_RETVAL_ERROR; goto init_pqos_events_exit; } @@ -401,7 +402,7 @@ all_evt_mask |= events; - init_pqos_events_exit: +init_pqos_events_exit: if (files > 0) { for (i = 0; i < files; i++) free(namelist[i]); @@ -410,15 +411,32 @@ return ret; } -int perf_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap) +int +perf_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap) { int ret; unsigned i; + struct stat st; ASSERT(cpu != NULL); UNUSED_PARAM(cap); + /** + * Perf monitoring not supported + */ + if (stat(PERF_MON_SUPPORT, &st) != 0) { + LOG_INFO("Perf monitoring not supported."); + return PQOS_RETVAL_RESOURCE; + + } else { + /* basic perf events are supported */ + events_tab[OS_MON_EVT_IDX_INST].supported = 1; + events_tab[OS_MON_EVT_IDX_CYC].supported = 1; + events_tab[OS_MON_EVT_IDX_IPC].supported = 1; + events_tab[OS_MON_EVT_IDX_LLC_MISS].supported = 1; + } + ret = set_arch_event_attrs(&all_evt_mask); if (ret != PQOS_RETVAL_OK) return ret; @@ -433,7 +451,7 @@ if (ret != PQOS_RETVAL_OK) return ret; - perf_mon_init_exit: +perf_mon_init_exit: for (i = 0; i < DIM(events_tab); i++) { if (!events_tab[i].supported) continue; @@ -483,7 +501,8 @@ struct perf_mon_supported_event *se; ASSERT(group != NULL); - ASSERT(group->perf != NULL); + ASSERT(group->intl != NULL); + ASSERT(group->intl->perf.ctx != NULL); /** * Check if monitoring cores/tasks @@ -504,7 +523,7 @@ */ for (i = 0; i < num_ctrs; i++) { int ret; - struct pqos_mon_perf_ctx *ctx = &group->perf[i]; + struct pqos_mon_perf_ctx *ctx = &group->intl->perf.ctx[i]; int *fd; int core = -1; pid_t tid = -1; @@ -524,7 +543,8 @@ ret = perf_setup_counter(&se->attrs, tid, core, -1, 0, fd); if (ret != PQOS_RETVAL_OK) { LOG_ERROR("Failed to start perf " - "counters for %s\n", se->desc); + "counters for %s\n", + se->desc); return PQOS_RETVAL_ERROR; } } @@ -538,7 +558,8 @@ int i, num_ctrs; ASSERT(group != NULL); - ASSERT(group->perf != NULL); + ASSERT(group->intl != NULL); + ASSERT(group->intl->perf.ctx != NULL); /** * Check if monitoring cores/tasks @@ -554,7 +575,7 @@ * For each counter, close associated file descriptor */ for (i = 0; i < num_ctrs; i++) { - struct pqos_mon_perf_ctx *ctx = &group->perf[i]; + struct pqos_mon_perf_ctx *ctx = &group->intl->perf.ctx[i]; int *fd = perf_mon_get_fd(ctx, event); if (fd == NULL) @@ -592,7 +613,8 @@ uint64_t old_value; ASSERT(group != NULL); - ASSERT(group->perf != NULL); + ASSERT(group->intl != NULL); + ASSERT(group->intl->perf.ctx != NULL); /** * Check if monitoring cores/tasks @@ -608,7 +630,7 @@ * For each task read counter and sum of all counter values */ for (i = 0; i < num_ctrs; i++) { - struct pqos_mon_perf_ctx *ctx = &group->perf[i]; + struct pqos_mon_perf_ctx *ctx = &group->intl->perf.ctx[i]; uint64_t counter_value; int *fd = perf_mon_get_fd(ctx, event); @@ -632,31 +654,31 @@ old_value = group->values.mbm_local; group->values.mbm_local = value; group->values.mbm_local_delta = - get_delta(old_value, group->values.mbm_local); + get_delta(old_value, group->values.mbm_local); break; case PQOS_MON_EVENT_TMEM_BW: old_value = group->values.mbm_total; group->values.mbm_total = value; group->values.mbm_total_delta = - get_delta(old_value, group->values.mbm_total); + get_delta(old_value, group->values.mbm_total); break; case PQOS_PERF_EVENT_LLC_MISS: old_value = group->values.llc_misses; group->values.llc_misses = value; group->values.llc_misses_delta = - get_delta(old_value, group->values.llc_misses); + get_delta(old_value, group->values.llc_misses); break; case (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES: old_value = group->values.ipc_unhalted; group->values.ipc_unhalted = value; group->values.ipc_unhalted_delta = - get_delta(old_value, group->values.ipc_unhalted); + get_delta(old_value, group->values.ipc_unhalted); break; case (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS: old_value = group->values.ipc_retired; group->values.ipc_retired = value; group->values.ipc_retired_delta = - get_delta(old_value, group->values.ipc_retired); + get_delta(old_value, group->values.ipc_retired); break; default: return PQOS_RETVAL_ERROR; diff -Nru intel-cmt-cat-3.2/lib/perf_monitoring.h intel-cmt-cat-4.0/lib/perf_monitoring.h --- intel-cmt-cat-3.2/lib/perf_monitoring.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perf_monitoring.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,7 +121,6 @@ */ int perf_mon_is_event_supported(const enum pqos_mon_event event); - #ifdef __cplusplus } #endif diff -Nru intel-cmt-cat-3.2/lib/perl/Makefile.PL intel-cmt-cat-4.0/lib/perl/Makefile.PL --- intel-cmt-cat-3.2/lib/perl/Makefile.PL 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perl/Makefile.PL 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/perl/MANIFEST intel-cmt-cat-4.0/lib/perl/MANIFEST --- intel-cmt-cat-3.2/lib/perl/MANIFEST 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perl/MANIFEST 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/perl/pqos.i intel-cmt-cat-4.0/lib/perl/pqos.i --- intel-cmt-cat-3.2/lib/perl/pqos.i 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perl/pqos.i 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/perl/test.pl intel-cmt-cat-4.0/lib/perl/test.pl --- intel-cmt-cat-3.2/lib/perl/test.pl 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/perl/test.pl 2020-06-19 10:42:55.000000000 +0000 @@ -3,7 +3,7 @@ ############################################################################### # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/pqos.h intel-cmt-cat-4.0/lib/pqos.h --- intel-cmt-cat-3.2/lib/pqos.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/pqos.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,24 +57,25 @@ * ======================================= */ -#define PQOS_VERSION 30200 /**< version 3.2.0 */ -#define PQOS_MAX_L3CA_COS 16 /**< 16 x COS */ -#define PQOS_MAX_L2CA_COS 16 /**< 16 x COS */ +#define PQOS_VERSION 40000 /**< version 4.0.0 */ +#define PQOS_MAX_COS 16 /** 16 x COS */ +#define PQOS_MAX_L3CA_COS PQOS_MAX_COS +#define PQOS_MAX_L2CA_COS PQOS_MAX_COS /* * ======================================= * Return values * ======================================= */ -#define PQOS_RETVAL_OK 0 /**< everything OK */ -#define PQOS_RETVAL_ERROR 1 /**< generic error */ -#define PQOS_RETVAL_PARAM 2 /**< parameter error */ -#define PQOS_RETVAL_RESOURCE 3 /**< resource error */ -#define PQOS_RETVAL_INIT 4 /**< initialization error */ +#define PQOS_RETVAL_OK 0 /**< everything OK */ +#define PQOS_RETVAL_ERROR 1 /**< generic error */ +#define PQOS_RETVAL_PARAM 2 /**< parameter error */ +#define PQOS_RETVAL_RESOURCE 3 /**< resource error */ +#define PQOS_RETVAL_INIT 4 /**< initialization error */ #define PQOS_RETVAL_TRANSPORT 5 /**< transport error */ -#define PQOS_RETVAL_PERF_CTR 6 /**< performance counter error */ -#define PQOS_RETVAL_BUSY 7 /**< resource busy error */ -#define PQOS_RETVAL_INTER 8 /**< Interface not supported */ +#define PQOS_RETVAL_PERF_CTR 6 /**< performance counter error */ +#define PQOS_RETVAL_BUSY 7 /**< resource busy error */ +#define PQOS_RETVAL_INTER 8 /**< Interface not supported */ /* * ======================================= @@ -293,6 +294,7 @@ enum pqos_mon_event type; /**< event type */ unsigned max_rmid; /**< max RMID supported for this event */ uint32_t scale_factor; /**< factor to scale RMID value to bytes */ + unsigned counter_length; /**< counter bit length */ }; struct pqos_cap_mon { @@ -354,12 +356,24 @@ }; /** + * ======================================= + * Vendor values + * ======================================= + */ +enum pqos_vendor { + PQOS_VENDOR_UNKNOWN = 0, /**< UNKNOWN */ + PQOS_VENDOR_INTEL = 1, /**< INTEL */ + PQOS_VENDOR_AMD = 2 /**< AMD */ +}; + +/** * CPU topology structure */ struct pqos_cpuinfo { unsigned mem_size; /**< byte size of the structure */ struct pqos_cacheinfo l2; /**< L2 cache information */ struct pqos_cacheinfo l3; /**< L3 cache information */ + enum pqos_vendor vendor; /**< vendor Intel/AMD */ unsigned num_cores; /**< number of cores in the system */ struct pqos_coreinfo cores[0]; }; @@ -405,26 +419,7 @@ uint64_t llc_misses_delta; /**< LLC misses - delta */ }; -/** - * Core monitoring poll context - */ -struct pqos_mon_poll_ctx { - unsigned lcore; - unsigned cluster; - pqos_rmid_t rmid; -}; - -/** - * Perf monitoring poll context - */ -struct pqos_mon_perf_ctx { - int fd_llc; - int fd_mbl; - int fd_mbt; - int fd_inst; - int fd_cyc; - int fd_llc_misses; -}; +struct pqos_mon_data_internal; /** * Monitoring group data structure @@ -448,31 +443,12 @@ pid_t *tid_map; /** - * Perf specific section - */ - struct pqos_mon_perf_ctx *perf; /**< Perf poll context for each - core/tid */ - enum pqos_mon_event perf_event; /**< Started perf events */ - - /** - * Resctrl specific section - */ - enum pqos_mon_event resctrl_event; - char *resctrl_mon_group; - struct pqos_event_values resctrl_values_storage; /**< stores values - of monitoring group - that was moved to - another COS */ - - /** * Core specific section */ - struct pqos_mon_poll_ctx *poll_ctx; /**< core, cluster & RMID */ - unsigned num_poll_ctx; /**< number of poll contexts */ - unsigned *cores; /**< list of cores in the group */ - unsigned num_cores; /**< number of cores in the group */ - int valid_mbm_read; /**< flag to discard 1st invalid - read */ + unsigned *cores; /**< list of cores in the group */ + unsigned num_cores; /**< number of cores in the group */ + + struct pqos_mon_data_internal *intl; /**< internal data */ }; /** @@ -1253,6 +1229,16 @@ int *ctrl_enabled); /** + * @brief returns the CPU vendor identification + * + * @param [in] cpu CPU information structure from \a pqos_cap_get + * @retval 0 if vendor unknown + * @return 1 if the vendor is Intel + * @return 2 if the vendor is AMD + */ +enum pqos_vendor pqos_get_vendor(const struct pqos_cpuinfo *cpu); + +/** * @brief Retrieves a monitoring value from a group for a specific event. * @param [out] value monitoring value * @param [in] event_id event being monitored diff -Nru intel-cmt-cat-3.2/lib/python/Makefile intel-cmt-cat-4.0/lib/python/Makefile --- intel-cmt-cat-3.2/lib/python/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -16,7 +16,7 @@ test: test_env @bash -c "source test_env/bin/activate && \ - python -m coverage run --source . \ + python -m coverage run --source pqos \ -m unittest discover pqos/test -v; \ deactivate" @@ -26,12 +26,20 @@ --omit test_env/*.py,pqos/test/*.py,setup.py; \ deactivate" -style: test_env +pylint: test_env @bash -c "source test_env/bin/activate && \ python -m pylint pqos/*.py pqos/test/*.py && \ - python -m bandit *.py pqos/*.py; \ deactivate" +bandit: test_env + @bash -c "source test_env/bin/activate && \ + python -m bandit *.py pqos/*.py && \ + deactivate" + +style: + ${MAKE} pylint + ${MAKE} bandit + clean: @rm -rf test_env @rm -rf pqos/__pycache__ pqos/*.pyc diff -Nru intel-cmt-cat-3.2/lib/python/pqos/allocation.py intel-cmt-cat-4.0/lib/python/pqos/allocation.py --- intel-cmt-cat-3.2/lib/python/pqos/allocation.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/allocation.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/capability.py intel-cmt-cat-4.0/lib/python/pqos/capability.py --- intel-cmt-cat-3.2/lib/python/pqos/capability.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/capability.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -104,6 +104,7 @@ (u"type", ctypes.c_int), (u"max_rmid", ctypes.c_uint), (u"scale_factor", ctypes.c_uint32), + (u"counter_length", ctypes.c_uint), ] diff -Nru intel-cmt-cat-3.2/lib/python/pqos/common.py intel-cmt-cat-4.0/lib/python/pqos/common.py --- intel-cmt-cat-3.2/lib/python/pqos/common.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/common.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/cpuinfo.py intel-cmt-cat-4.0/lib/python/pqos/cpuinfo.py --- intel-cmt-cat-3.2/lib/python/pqos/cpuinfo.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/cpuinfo.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -49,10 +49,12 @@ # pylint: disable=too-few-public-methods _fields_ = [ - (u"lcore", ctypes.c_uint), # Logical core id - (u"socket", ctypes.c_uint), # Socket id in the system - (u"l3_id", ctypes.c_uint), # L3/LLC cluster id - (u"l2_id", ctypes.c_uint), # L2 cluster id + (u"lcore", ctypes.c_uint), # Logical core id + (u"socket", ctypes.c_uint), # Socket id in the system + (u"l3_id", ctypes.c_uint), # L3/LLC cluster id + (u"l2_id", ctypes.c_uint), # L2 cluster id + (u"l3cat_id", ctypes.c_uint), # L3 CAT classes id + (u"mba_id", ctypes.c_uint), # MBA id ] @@ -75,10 +77,15 @@ "pqos_cpuinfo structure" # pylint: disable=too-few-public-methods + PQOS_VENDOR_UNKNOWN = 0 + PQOS_VENDOR_INTEL = 1 + PQOS_VENDOR_AMD = 2 + _fields_ = [ (u"mem_size", ctypes.c_uint), # Byte size of the structure (u"l2", CPqosCacheInfo), # L2 cache information (u"l3", CPqosCacheInfo), # L3 cache information + (u"vendor", ctypes.c_int), # CPU vendor (u"num_cores", ctypes.c_uint), # Number of cores in the system (u"cores", CPqosCoreInfo * 0) # Core information ] @@ -86,13 +93,15 @@ class PqosCoreInfo(object): "Core information" - # pylint: disable=too-few-public-methods + # pylint: disable=too-few-public-methods, too-many-arguments - def __init__(self, core, socket, l3_id, l2_id): + def __init__(self, core, socket, l3_id, l2_id, l3cat_id, mba_id): self.core = core self.socket = socket self.l3_id = l3_id self.l2_id = l2_id + self.l3cat_id = l3cat_id + self.mba_id = mba_id def _get_array_items(count, p_items): @@ -174,6 +183,25 @@ pqos_handle_error(func.__name__, ret) return result.value + def get_vendor(self): + """ + Retrieves CPU vendor information from CPU info structure + + Returns: + CPU vendor + """ + func = self.pqos.lib.pqos_get_vendor + func.restype = ctypes.c_int + + vendor = func(self.p_cpu) + + if vendor == CPqosCpuInfo.PQOS_VENDOR_INTEL: + return u"INTEL" + if vendor == CPqosCpuInfo.PQOS_VENDOR_AMD: + return u"AMD" + + return u"UNKNOWN" + def get_sockets(self): """ Retrieves socket IDs from CPU info structure. @@ -244,7 +272,9 @@ coreinfo = PqosCoreInfo(core=coreinfo_struct.lcore, socket=coreinfo_struct.socket, l3_id=coreinfo_struct.l3_id, - l2_id=coreinfo_struct.l2_id) + l2_id=coreinfo_struct.l2_id, + l3cat_id=coreinfo_struct.l3cat_id, + mba_id=coreinfo_struct.mba_id) return coreinfo def get_one_core(self, socket): diff -Nru intel-cmt-cat-3.2/lib/python/pqos/error.py intel-cmt-cat-4.0/lib/python/pqos/error.py --- intel-cmt-cat-3.2/lib/python/pqos/error.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/error.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/__init__.py intel-cmt-cat-4.0/lib/python/pqos/__init__.py --- intel-cmt-cat-3.2/lib/python/pqos/__init__.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/__init__.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/l2ca.py intel-cmt-cat-4.0/lib/python/pqos/l2ca.py --- intel-cmt-cat-3.2/lib/python/pqos/l2ca.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/l2ca.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/l3ca.py intel-cmt-cat-4.0/lib/python/pqos/l3ca.py --- intel-cmt-cat-3.2/lib/python/pqos/l3ca.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/l3ca.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/mba.py intel-cmt-cat-4.0/lib/python/pqos/mba.py --- intel-cmt-cat-3.2/lib/python/pqos/mba.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/mba.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/monitoring.py intel-cmt-cat-4.0/lib/python/pqos/monitoring.py --- intel-cmt-cat-3.2/lib/python/pqos/monitoring.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/monitoring.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ from pqos.capability import CPqosMonitor -RMID_T = ctypes.c_uint32 +RmidT = ctypes.c_uint32 class CPqosEventValues(ctypes.Structure): @@ -69,31 +69,6 @@ ] -class CPqosMonPollCtx(ctypes.Structure): - "pqos_mon_poll_ctx structure" - # pylint: disable=too-few-public-methods - - _fields_ = [ - (u'lcore', ctypes.c_uint), - (u'cluster', ctypes.c_uint), - (u'rmid', RMID_T) - ] - - -class CPqosMonPerfCtx(ctypes.Structure): - "pqos_mon_perf_ctx structure" - # pylint: disable=too-few-public-methods - - _fields_ = [ - (u'fd_llc', ctypes.c_int), - (u'fd_mbl', ctypes.c_int), - (u'fd_mbt', ctypes.c_int), - (u'fd_inst', ctypes.c_int), - (u'fd_cyc', ctypes.c_int), - (u'fd_llc_misses', ctypes.c_int) - ] - - class CPqosMonData(ctypes.Structure): "pqos_mon_data structure" @@ -106,16 +81,9 @@ (u'pids', ctypes.POINTER(ctypes.c_uint)), (u'tid_nr', ctypes.c_uint), (u'tid_map', ctypes.POINTER(ctypes.c_uint)), - (u'perf', ctypes.POINTER(CPqosMonPerfCtx)), - (u'perf_event', ctypes.c_uint), - (u'resctrl_event', ctypes.c_uint), - (u'resctrl_mon_group', ctypes.c_char_p), - (u'resctrl_values_storage', CPqosEventValues), - (u'poll_ctx', ctypes.POINTER(CPqosMonPollCtx)), - (u'num_poll_ctx', ctypes.c_uint), (u'cores', ctypes.POINTER(ctypes.c_uint)), (u'num_cores', ctypes.c_uint), - (u'valid_mbm_read', ctypes.c_int) + (u'intl', ctypes.c_void_p) ] def __init__(self, *args, **kwargs): @@ -206,7 +174,7 @@ RMID for a given core """ - rmid = RMID_T(0) + rmid = RmidT(0) rmid_ref = ctypes.byref(rmid) ret = self.pqos.lib.pqos_mon_assoc_get(core, rmid_ref) pqos_handle_error(u'pqos_mon_assoc_get', ret) diff -Nru intel-cmt-cat-3.2/lib/python/pqos/pqos.py intel-cmt-cat-4.0/lib/python/pqos/pqos.py --- intel-cmt-cat-3.2/lib/python/pqos/pqos.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/pqos.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -39,7 +39,6 @@ from __future__ import absolute_import, division, print_function import ctypes -from ctypes.util import find_library import sys from pqos.common import pqos_handle_error @@ -113,12 +112,7 @@ def __init__(self): "Finds PQoS library and constructs a new object." - libpqos_path = find_library(u'pqos') - - if not libpqos_path: - raise Exception(u'Cannot find libpqos') - - self.lib = ctypes.cdll.LoadLibrary(libpqos_path) + self.lib = ctypes.cdll.LoadLibrary(u'libpqos.so.4') def init(self, interface, log_file=None, log_callback=None, log_context=None, verbose=u'default'): diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/helper.py intel-cmt-cat-4.0/lib/python/pqos/test/helper.py --- intel-cmt-cat-3.2/lib/python/pqos/test/helper.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/helper.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/__init__.py intel-cmt-cat-4.0/lib/python/pqos/test/__init__.py --- intel-cmt-cat-3.2/lib/python/pqos/test/__init__.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/__init__.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/mock_pqos.py intel-cmt-cat-4.0/lib/python/pqos/test/mock_pqos.py --- intel-cmt-cat-3.2/lib/python/pqos/test/mock_pqos.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/mock_pqos.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_allocation.py intel-cmt-cat-4.0/lib/python/pqos/test/test_allocation.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_allocation.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_allocation.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_capability.py intel-cmt-cat-4.0/lib/python/pqos/test/test_capability.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_capability.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_capability.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_cpuinfo.py intel-cmt-cat-4.0/lib/python/pqos/test/test_cpuinfo.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_cpuinfo.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_cpuinfo.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -77,8 +77,8 @@ def build_core_infos(self): # pylint: disable=no-self-use "Builds core information." - core_info1 = CPqosCoreInfo(lcore=0, socket=0, l3_id=0, l2_id=0) - core_info2 = CPqosCoreInfo(lcore=1, socket=0, l3_id=0, l2_id=1) + core_info1 = CPqosCoreInfo(lcore=0, socket=0, l3_id=0, l2_id=0, l3cat_id=0, mba_id=0) + core_info2 = CPqosCoreInfo(lcore=1, socket=0, l3_id=0, l2_id=1, l3cat_id=0, mba_id=0) return [core_info1, core_info2] def build(self): @@ -150,6 +150,17 @@ lib.pqos_cap_get.assert_called_once() @mock_pqos_lib + def test_get_vendor(self, lib): + "Tests get_vendor() method" + + lib.pqos_cap_get = MagicMock(return_value=0) + lib.pqos_get_vendor = MagicMock(return_value=1) + + cpu = PqosCpuInfo() + + self.assertEqual(cpu.get_vendor(), "INTEL") + + @mock_pqos_lib def test_get_sockets(self, lib): "Tests get_sockets() method." @@ -265,7 +276,7 @@ def test_get_core_info(self, lib): "Tests get_core_info() method." - coreinfo_mock = CPqosCoreInfo(lcore=1, socket=0, l3_id=1, l2_id=7) + coreinfo_mock = CPqosCoreInfo(lcore=1, socket=0, l3_id=1, l2_id=7, l3cat_id=1, mba_id=1) def pqos_get_core_info_m(_p_cpu, core): "Mock pqos_cpu_get_core_info()." diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_l2ca.py intel-cmt-cat-4.0/lib/python/pqos/test/test_l2ca.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_l2ca.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_l2ca.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_l3ca.py intel-cmt-cat-4.0/lib/python/pqos/test/test_l3ca.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_l3ca.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_l3ca.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_mba.py intel-cmt-cat-4.0/lib/python/pqos/test/test_mba.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_mba.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_mba.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_monitoring.py intel-cmt-cat-4.0/lib/python/pqos/test/test_monitoring.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_monitoring.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_monitoring.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/pqos/test/test_pqos.py intel-cmt-cat-4.0/lib/python/pqos/test/test_pqos.py --- intel-cmt-cat-3.2/lib/python/pqos/test/test_pqos.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/pqos/test/test_pqos.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/python/.pylintrc intel-cmt-cat-4.0/lib/python/.pylintrc --- intel-cmt-cat-3.2/lib/python/.pylintrc 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/.pylintrc 2020-06-19 10:42:55.000000000 +0000 @@ -22,7 +22,7 @@ # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. -load-plugins= +load-plugins=caniusepython3.pylint_checker # Pickle collected data for later comparisons. persistent=yes diff -Nru intel-cmt-cat-3.2/lib/python/requirements.txt intel-cmt-cat-4.0/lib/python/requirements.txt --- intel-cmt-cat-3.2/lib/python/requirements.txt 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/requirements.txt 2020-06-19 10:42:55.000000000 +0000 @@ -2,3 +2,4 @@ bandit pylint coverage +caniusepython3 diff -Nru intel-cmt-cat-3.2/lib/python/setup.py intel-cmt-cat-4.0/lib/python/setup.py --- intel-cmt-cat-3.2/lib/python/setup.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/python/setup.py 2020-06-19 10:42:55.000000000 +0000 @@ -5,7 +5,7 @@ setup( name='pqos', - version='3.2.0', + version='4.0.0', maintainer='Intel', maintainer_email='adrianx.boczkowski@intel.com', packages=['pqos', 'pqos.test'], diff -Nru intel-cmt-cat-3.2/lib/resctrl_alloc.c intel-cmt-cat-4.0/lib/resctrl_alloc.c --- intel-cmt-cat-3.2/lib/resctrl_alloc.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_alloc.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include "cap.h" #include "resctrl_alloc.h" #include "resctrl_utils.h" +#include "resctrl_monitoring.h" /** * --------------------------------------- @@ -154,7 +155,7 @@ if (result < 0) return NULL; - fd = fopen_check_symlink(buf, mode); + fd = pqos_fopen(buf, mode); if (fd == NULL) LOG_ERROR("Could not open %s file %s for COS %u\n", name, buf, class_id); @@ -507,8 +508,12 @@ int resctrl_alloc_assoc_set(const unsigned lcore, const unsigned class_id) { - int ret; + int ret, ret_mon; struct resctrl_cpumask mask; + char name[32]; + + /* check if core is assigned to monitoring group */ + ret_mon = resctrl_mon_assoc_get(lcore, name, DIM(name)); ret = resctrl_alloc_cpumask_read(class_id, &mask); if (ret != PQOS_RETVAL_OK) @@ -518,6 +523,10 @@ ret = resctrl_alloc_cpumask_write(class_id, &mask); + /* assign core back to monitoring group */ + if (ret_mon == PQOS_RETVAL_OK) + resctrl_mon_assoc_set(lcore, name); + return ret; } diff -Nru intel-cmt-cat-3.2/lib/resctrl_alloc.h intel-cmt-cat-4.0/lib/resctrl_alloc.h --- intel-cmt-cat-3.2/lib/resctrl_alloc.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_alloc.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/resctrl.c intel-cmt-cat-4.0/lib/resctrl.c --- intel-cmt-cat-3.2/lib/resctrl.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,9 @@ #include "log.h" #include "types.h" #include "resctrl.h" +#include "common.h" +#include "cap.h" +#include "resctrl_alloc.h" static int resctrl_lock_fd = -1; /**< File descriptor to the lockfile */ @@ -147,6 +150,7 @@ { const char *options = NULL; char buf[32] = ""; + int ret = PQOS_RETVAL_OK; ASSERT(l3_cdp_cfg == PQOS_REQUIRE_CDP_ON || l3_cdp_cfg == PQOS_REQUIRE_CDP_OFF); @@ -156,30 +160,64 @@ /* l3 cdp mount option */ if (l3_cdp_cfg == PQOS_REQUIRE_CDP_ON) { - strcat(buf, "cdp"); + pqos_strcat(buf, "cdp", sizeof(buf)); options = buf; } /* l2 cdp mount option */ if (l2_cdp_cfg == PQOS_REQUIRE_CDP_ON) { if (options != NULL) - strcat(buf, ","); - strcat(buf, "cdpl2"); + pqos_strcat(buf, ",", sizeof(buf)); + pqos_strcat(buf, "cdpl2", sizeof(buf)); options = buf; } /* mba mount option */ if (mba_cfg == PQOS_MBA_CTRL) { if (options != NULL) - strcat(buf, ","); - strcat(buf, "mba_MBps"); + pqos_strcat(buf, ",", sizeof(buf)); + pqos_strcat(buf, "mba_MBps", sizeof(buf)); options = buf; } if (mount("resctrl", RESCTRL_PATH, "resctrl", 0, options) != 0) return PQOS_RETVAL_ERROR; - return PQOS_RETVAL_OK; + /* Check if mba ctrl is enabled */ + if (mba_cfg == PQOS_MBA_CTRL) { + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + struct resctrl_schemata *schmt; + struct pqos_mba mba; + + _pqos_cap_get(&cap, &cpu); + + schmt = resctrl_schemata_alloc(cap, cpu); + if (schmt == NULL) { + ret = PQOS_RETVAL_ERROR; + goto resctrl_mount_exit; + } + + ret = resctrl_alloc_schemata_read(0, schmt); + if (ret != PQOS_RETVAL_OK) { + resctrl_schemata_free(schmt); + goto resctrl_mount_exit; + } + + ret = resctrl_schemata_mba_get(schmt, 0, &mba); + if (ret == PQOS_RETVAL_OK && mba.mb_max <= 100) { + LOG_ERROR("MBA CTRL not enabled\n"); + ret = PQOS_RETVAL_ERROR; + } + + resctrl_schemata_free(schmt); + } + +resctrl_mount_exit: + if (ret != PQOS_RETVAL_OK) + resctrl_umount(); + + return ret; } int @@ -210,6 +248,17 @@ mask->tab[item] = mask->tab[item] | (1 << bit); } +void +resctrl_cpumask_unset(const unsigned lcore, struct resctrl_cpumask *mask) +{ + /* index in mask table */ + const unsigned item = (sizeof(mask->tab) - 1) - (lcore / CHAR_BIT); + const unsigned bit = lcore % CHAR_BIT; + + /* Clear lcore bit in mask table item */ + mask->tab[item] &= ~(1 << bit); +} + int resctrl_cpumask_get(const unsigned lcore, const struct resctrl_cpumask *mask) { diff -Nru intel-cmt-cat-3.2/lib/resctrl.h intel-cmt-cat-4.0/lib/resctrl.h --- intel-cmt-cat-3.2/lib/resctrl.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,15 +48,15 @@ #ifndef RESCTRL_PATH #define RESCTRL_PATH "/sys/fs/resctrl" #endif -#define RESCTRL_PATH_INFO RESCTRL_PATH "/info" +#define RESCTRL_PATH_INFO RESCTRL_PATH "/info" #define RESCTRL_PATH_INFO_L3_MON RESCTRL_PATH_INFO "/L3_MON" -#define RESCTRL_PATH_INFO_L3 RESCTRL_PATH_INFO "/L3" +#define RESCTRL_PATH_INFO_L3 RESCTRL_PATH_INFO "/L3" #define RESCTRL_PATH_INFO_L3CODE RESCTRL_PATH_INFO "/L3CODE" #define RESCTRL_PATH_INFO_L3DATA RESCTRL_PATH_INFO "/L3DATA" -#define RESCTRL_PATH_INFO_L2 RESCTRL_PATH_INFO "/L2" +#define RESCTRL_PATH_INFO_L2 RESCTRL_PATH_INFO "/L2" #define RESCTRL_PATH_INFO_L2CODE RESCTRL_PATH_INFO "/L2CODE" #define RESCTRL_PATH_INFO_L2DATA RESCTRL_PATH_INFO "/L2DATA" -#define RESCTRL_PATH_INFO_MB RESCTRL_PATH_INFO "/MB" +#define RESCTRL_PATH_INFO_MB RESCTRL_PATH_INFO "/MB" /** * Max supported number of CPU's @@ -132,6 +132,14 @@ void resctrl_cpumask_set(const unsigned lcore, struct resctrl_cpumask *mask); /** + * @brief Unset lcore bit in cpu mask + * + * @param [in] lcore Core number + * @param [in] cpumask Modified cpu mask + */ +void resctrl_cpumask_unset(const unsigned lcore, struct resctrl_cpumask *mask); + +/** * @brief Check if lcore is set in cpu mask * * @param [in] lcore Core number diff -Nru intel-cmt-cat-3.2/lib/resctrl_monitoring.c intel-cmt-cat-4.0/lib/resctrl_monitoring.c --- intel-cmt-cat-3.2/lib/resctrl_monitoring.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_monitoring.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,10 +46,13 @@ #include "types.h" #include "cap.h" #include "common.h" +#include "monitoring.h" #include "resctrl.h" #include "resctrl_monitoring.h" #include "resctrl_alloc.h" +#define GROUP_NAME_PREFIX "pqos-" + /** * --------------------------------------- * Local data structures @@ -79,6 +82,25 @@ return (dir->d_name[0] == '.') ? 0 : 1; } +/** + * @breif Free memory allocated by scandir + * + * @param namelist structure allocated by scandir + * @param count number of files + */ +static void +free_scandir(struct dirent **namelist, int count) +{ + int i; + + if (count < 0) + return; + + for (i = 0; i < count; i++) + free(namelist[i]); + free(namelist); +} + int resctrl_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap) { @@ -100,7 +122,7 @@ /** * Discover supported events */ - fd = fopen_check_symlink(RESCTRL_PATH_INFO_L3_MON "/mon_features", "r"); + fd = pqos_fopen(RESCTRL_PATH_INFO_L3_MON "/mon_features", "r"); if (fd == NULL) { LOG_ERROR("Failed to obtain resctrl monitoring features\n"); return PQOS_RETVAL_ERROR; @@ -281,7 +303,7 @@ resctrl_mon_group_path(class_id, resctrl_group, "/cpus", path, sizeof(path)); - fd = fopen_check_symlink(path, "w"); + fd = pqos_fopen(path, "w"); if (fd == NULL) return PQOS_RETVAL_ERROR; @@ -317,7 +339,7 @@ resctrl_mon_group_path(class_id, resctrl_group, "/cpus", path, sizeof(path)); - fd = fopen_check_symlink(path, "r"); + fd = pqos_fopen(path, "r"); if (fd == NULL) return PQOS_RETVAL_ERROR; @@ -333,6 +355,7 @@ * * @param [in] class_id COS id * @param [in] resctrl_group mon group name + * @param [in] l3id l3id to read from * @param [in] event resctrl mon event * @param [out] value counter value * @@ -340,17 +363,17 @@ * @retval PQOS_RETVAL_OK on success */ static int -resctrl_mon_read_counters(const unsigned class_id, - const char *resctrl_group, - const enum pqos_mon_event event, - uint64_t *value) +resctrl_mon_read_counter(const unsigned class_id, + const char *resctrl_group, + const unsigned l3id, + const enum pqos_mon_event event, + uint64_t *value) { - int ret = PQOS_RETVAL_OK; - unsigned *l3cat_ids = NULL; - unsigned l3cat_id_num; - unsigned l3cat_id; char buf[128]; const char *name; + char path[PATH_MAX]; + FILE *fd; + unsigned long long counter; ASSERT(resctrl_group != NULL); ASSERT(value != NULL); @@ -374,42 +397,142 @@ *value = 0; resctrl_mon_group_path(class_id, resctrl_group, NULL, buf, sizeof(buf)); + snprintf(path, sizeof(path), "%s/mon_data/mon_L3_%02u/%s", buf, l3id, + name); + fd = pqos_fopen(path, "r"); + if (fd == NULL) + return PQOS_RETVAL_ERROR; + if (fscanf(fd, "%llu", &counter) == 1) + *value = counter; + fclose(fd); - l3cat_ids = pqos_cpu_get_l3cat_ids(m_cpu, &l3cat_id_num); - if (l3cat_ids == NULL) { - ret = PQOS_RETVAL_ERROR; - goto resctrl_mon_read_exit; - } + return PQOS_RETVAL_OK; +} - for (l3cat_id = 0; l3cat_id < l3cat_id_num; l3cat_id++) { - char path[PATH_MAX]; - FILE *fd; - unsigned long long counter; +/** + * @brief Read counter value from requested \a l3ids + * + * @param [in] class_id COS id + * @param [in] resctrl_group mon group name + * @param [in] event resctrl mon event + * @param [in] l3ids l3ids to read from + * @param [in] l3ids_num number of l3ids + * @param [in] event monitoring event + * @param [out] value counter value + * + * @return Operational status + * @retval PQOS_RETVAL_OK on success + */ +static int +resctrl_mon_read_counters(const unsigned class_id, + const char *resctrl_group, + unsigned *l3ids, + unsigned l3ids_num, + const enum pqos_mon_event event, + uint64_t *value) +{ + int ret = PQOS_RETVAL_OK; + unsigned *l3cat_ids = NULL; + unsigned l3cat_id_num; + unsigned l3cat_id; + + ASSERT(resctrl_group != NULL); + ASSERT(value != NULL); + + *value = 0; - snprintf(path, sizeof(path), "%s/mon_data/mon_L3_%02u/%s", buf, - l3cat_ids[l3cat_id], name); - fd = fopen_check_symlink(path, "r"); - if (fd == NULL) { + if (l3ids == NULL) { + l3cat_ids = pqos_cpu_get_l3cat_ids(m_cpu, &l3cat_id_num); + if (l3cat_ids == NULL) { ret = PQOS_RETVAL_ERROR; goto resctrl_mon_read_exit; } - if (fscanf(fd, "%llu", &counter) == 1) - *value += counter; - fclose(fd); + } else { + l3cat_ids = l3ids; + l3cat_id_num = l3ids_num; + } + + for (l3cat_id = 0; l3cat_id < l3cat_id_num; l3cat_id++) { + const unsigned l3id = l3cat_ids[l3cat_id]; + uint64_t counter; + + ret = resctrl_mon_read_counter(class_id, resctrl_group, l3id, + event, &counter); + if (ret != PQOS_RETVAL_OK) + goto resctrl_mon_read_exit; + + *value += counter; } resctrl_mon_read_exit: - if (l3cat_ids != NULL) + if (l3ids == NULL && l3cat_ids != NULL) free(l3cat_ids); return ret; } /** - * @brief Check if mon group is empty (no cores/tasks assigned) + * @brief Obtain max threshold occupancy + * + * @param [out] value max threshold occupancy value + * + * @return Operational status + * @retval PQOS_RETVAL_OK on success + */ +static int +restrl_mon_get_max_llc_tresh(unsigned *value) +{ + int ret = PQOS_RETVAL_OK; + FILE *fd; + + fd = pqos_fopen(RESCTRL_PATH "/info/L3_MON/max_threshold_occupancy", + "r"); + if (fd == NULL) + return PQOS_RETVAL_ERROR; + if (fscanf(fd, "%u", value) != 1) + ret = PQOS_RETVAL_ERROR; + fclose(fd); + + return ret; +} + +/** + * @brief Check if file is empty + * + * @param [in] path file path + * + * @return If file is empty + * @retval 1 if file is empty + */ +static int +resctrl_mon_file_empty(const char *path) +{ + int empty = 1; + char buf[128]; + + FILE *fd = pqos_fopen(path, "r"); + + if (fd == NULL) + return -1; + memset(buf, 0, sizeof(buf)); + /* Try to read from file */ + while (fgets(buf, sizeof(buf), fd) != NULL) + if (buf[0] != '\n') { + empty = 0; + break; + } + fclose(fd); + + return empty; +} + +/** + * @brief Check if monitored group is junk (no cores/tasks assigned/low llc) * * @param [in] class_id COS id * @param [in] resctrl_group mon group name + * @param [in] l3id l3ids to read from + * @param [in] l3id_num number of l3ids * @param [out] empty 1 when group is empty * * @return Operational status @@ -418,14 +541,13 @@ static int resctrl_mon_empty(const unsigned class_id, const char *resctrl_group, + unsigned *l3id, + unsigned l3id_num, int *empty) { int ret; - FILE *fd; + int retval; char path[128]; - char buf[128]; - struct resctrl_cpumask mask; - unsigned i; unsigned max_threshold_occupancy; uint64_t value; @@ -437,32 +559,28 @@ /* * Some cores are assigned to group? */ - ret = resctrl_mon_cpumask_read(class_id, resctrl_group, &mask); - if (ret != PQOS_RETVAL_OK) - return ret; - - for (i = 0; i < sizeof(mask.tab); i++) - if (mask.tab[i] > 0) { - *empty = 0; - return PQOS_RETVAL_OK; - } + resctrl_mon_group_path(class_id, resctrl_group, "/cpus_list", path, + sizeof(path)); + retval = resctrl_mon_file_empty(path); + if (retval < 0) + return PQOS_RETVAL_ERROR; + else if (!retval) { + *empty = 0; + return PQOS_RETVAL_OK; + } /* *Some tasks are assigned to group? */ resctrl_mon_group_path(class_id, resctrl_group, "/tasks", path, sizeof(path)); - fd = fopen_check_symlink(path, "r"); - if (fd == NULL) + retval = resctrl_mon_file_empty(path); + if (retval < 0) return PQOS_RETVAL_ERROR; - /* Search tasks file for any task ID */ - memset(buf, 0, sizeof(buf)); - if (fgets(buf, sizeof(buf), fd) != NULL) { + else if (!retval) { *empty = 0; - fclose(fd); return PQOS_RETVAL_OK; } - fclose(fd); /* * Check if llc occupancy is lower than max_occupancy_threshold @@ -470,20 +588,16 @@ if ((supported_events & PQOS_MON_EVENT_L3_OCCUP) == 0) return PQOS_RETVAL_OK; - ret = resctrl_mon_read_counters(class_id, resctrl_group, + ret = resctrl_mon_read_counters(class_id, resctrl_group, l3id, l3id_num, PQOS_MON_EVENT_L3_OCCUP, &value); if (ret != PQOS_RETVAL_OK) return ret; - fd = fopen_check_symlink( - RESCTRL_PATH "/info/L3_MON/max_threshold_occupancy", "r"); - if (fd == NULL) - return PQOS_RETVAL_ERROR; - if (fscanf(fd, "%u", &max_threshold_occupancy) != 1) - ret = PQOS_RETVAL_ERROR; - else if (value > max_threshold_occupancy) + ret = restrl_mon_get_max_llc_tresh(&max_threshold_occupancy); + if (ret != PQOS_RETVAL_OK) + return ret; + if (value > max_threshold_occupancy) *empty = 0; - fclose(fd); return ret; } @@ -574,7 +688,7 @@ ret = PQOS_RETVAL_RESOURCE; resctrl_mon_assoc_get_exit: - free(namelist); + free_scandir(namelist, num_groups); return ret; } @@ -690,7 +804,7 @@ resctrl_mon_group_path(class_id, namelist[i]->d_name, "/tasks", path, sizeof(path)); - fd = fopen_check_symlink(path, "r"); + fd = pqos_fopen(path, "r"); if (fd == NULL) goto resctrl_mon_assoc_get_pid_exit; @@ -720,7 +834,7 @@ ret = PQOS_RETVAL_RESOURCE; resctrl_mon_assoc_get_pid_exit: - free(namelist); + free_scandir(namelist, num_groups); return ret; } @@ -747,7 +861,7 @@ } strncat(path, "/tasks", sizeof(path) - strlen(path) - 1); - fd = fopen_check_symlink(path, "w"); + fd = pqos_fopen(path, "w"); if (fd == NULL) return PQOS_RETVAL_ERROR; @@ -763,34 +877,329 @@ return PQOS_RETVAL_OK; } +#define RESCTRL_CORE_MAX_L3ID 63 +struct resctrl_core_group { + char name[32]; + int valid; + uint64_t llc; + uint64_t l3ids; + time_t mtime; +}; + +/** + * @brief Parse resctrl core monitoring groups + * + * @param [out] cgrp Parser monitoring groups + * @param [out] cgrp_num Number of groups + * + * @return Operational status + * @retval PQOS_RETVAL_OK on success + */ +static int +resctrl_mon_parse(struct resctrl_core_group **cgrp, unsigned *cgrp_num) +{ + int ret = PQOS_RETVAL_OK; + unsigned cos = 0; + unsigned ctrl_grps; + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + const struct pqos_capability *cap_mon; + struct resctrl_core_group *grps = NULL; + unsigned grps_num = 0; + unsigned grps_size; + + _pqos_cap_get(&cap, &cpu); + + ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MON, &cap_mon); + if (ret != PQOS_RETVAL_OK) + return ret; + + ret = resctrl_alloc_get_grps_num(cap, &ctrl_grps); + if (ret != PQOS_RETVAL_OK) + return ret; + + grps_size = cap_mon->u.mon->max_rmid; + grps = calloc(grps_size, sizeof(*grps)); + if (grps == NULL) + return PQOS_RETVAL_RESOURCE; + + /* Build list of core monitroing groups */ + do { + struct dirent **namelist = NULL; + struct resctrl_cpumask cpumask; + int num_groups; + char dir[256]; + int i; + + resctrl_mon_group_path(cos, "", NULL, dir, sizeof(dir)); + num_groups = scandir(dir, &namelist, filter, NULL); + if (num_groups < 0) { + LOG_ERROR( + "Failed to read monitoring groups for COS %u\n", + cos); + ret = PQOS_RETVAL_ERROR; + goto resctrl_mon_parse_exit; + } + + for (i = 0; i < num_groups; i++) { + char path[256]; + const char *grp_name = namelist[i]->d_name; + struct resctrl_core_group *grp = NULL; + unsigned j; + int retval; + + /* group not managed by pqos library */ + if (strncmp(grp_name, GROUP_NAME_PREFIX, 5) != 0) + continue; + + /* Check if group already exists */ + for (j = 0; j < grps_num; j++) + if (strncmp(grp_name, grps[j].name, + DIM(grps[j].name)) == 0) { + grp = &grps[j]; + break; + } + /* new group */ + if (grp == NULL) { + if (grps_num + 1 == grps_size) { + ret = PQOS_RETVAL_ERROR; + break; + } + grp = &grps[grps_num++]; + strncpy(grp->name, grp_name, sizeof(grp->name)); + grp->name[sizeof(grp->name) - 1] = '\0'; + grp->valid = 1; + } + if (!grp->valid) + continue; + + /* Some tasks are assigned to group? */ + resctrl_mon_group_path(cos, grp->name, "/tasks", path, + sizeof(path)); + retval = resctrl_mon_file_empty(path); + if (retval < 0) { + ret = PQOS_RETVAL_ERROR; + break; + } else if (!retval) { + grp->valid = 0; + continue; + } + + /* Cores assigned to group */ + ret = + resctrl_mon_cpumask_read(cos, grp->name, &cpumask); + if (ret != PQOS_RETVAL_OK) + break; + + for (j = 0; j < cpu->num_cores; j++) { + const struct pqos_coreinfo *coreinfo = + &(cpu->cores[j]); + + if (resctrl_cpumask_get(coreinfo->lcore, + &cpumask)) { + if (coreinfo->l3cat_id >= + RESCTRL_CORE_MAX_L3ID) { + grp->valid = 0; + break; + } + grp->l3ids |= + (1LLU << coreinfo->l3cat_id); + } + } + } + free_scandir(namelist, num_groups); + + if (ret != PQOS_RETVAL_OK) + break; + } while (++cos < ctrl_grps); + +resctrl_mon_parse_exit: + if (ret != PQOS_RETVAL_OK) + free(grps); + else { + *cgrp = grps; + *cgrp_num = grps_num; + } + + return ret; +} + +/** + * @brief Assignes resctrl monitoring group + * + * @param group monitoring structure + * + * @return Resctrl monitoring group + */ +static char * +resctrl_mon_assign(struct pqos_mon_data *group) +{ + char *resctrl_group = group->intl->resctrl.mon_group; + struct resctrl_core_group *cgrp = NULL; + + /* search for available core group */ + if (resctrl_group == NULL && group->tid_nr == 0 && + group->num_cores > 0) { + int ret; + unsigned i; + unsigned l3ids = 0; + unsigned cgrp_num; + const struct pqos_cpuinfo *cpu; + const struct pqos_cap *cap; + unsigned max_threshold_occupancy; + unsigned max_cos; + + _pqos_cap_get(&cap, &cpu); + + /* list L3IDs for requested cores */ + for (i = 0; i < group->num_cores; i++) { + const struct pqos_coreinfo *coreinfo = + pqos_cpu_get_core_info(cpu, group->cores[i]); + + if (coreinfo == NULL) + return NULL; + if (coreinfo->l3cat_id > RESCTRL_CORE_MAX_L3ID) + goto mon_assign_new; + + l3ids |= (1LLU << coreinfo->l3cat_id); + } + + if ((supported_events & PQOS_MON_EVENT_L3_OCCUP) != 0) { + ret = restrl_mon_get_max_llc_tresh( + &max_threshold_occupancy); + if (ret != PQOS_RETVAL_OK) + return NULL; + } + + ret = resctrl_alloc_get_grps_num(cap, &max_cos); + if (ret != PQOS_RETVAL_OK) + return NULL; + + /* parse existing core monitoring groups */ + ret = resctrl_mon_parse(&cgrp, &cgrp_num); + if (ret != PQOS_RETVAL_OK) + return NULL; + + for (i = 0; i < cgrp_num; i++) { + struct resctrl_core_group *grp = &cgrp[i]; + uint64_t llc = 0; + unsigned l3id; + + if (!grp->valid) + continue; + + /* L3Ids overlap */ + if ((l3ids & grp->l3ids) != 0) + continue; + + /* check if llc doesn't occupancy threshold */ + if ((supported_events & PQOS_MON_EVENT_L3_OCCUP) != 0) { + for (l3id = 0; l3id < RESCTRL_CORE_MAX_L3ID; + l3id++) { + unsigned cos = 0; + + if ((l3ids & (1LLU << l3id)) == 0) + continue; + + do { + uint64_t val; + struct stat st; + char buf[128]; + + resctrl_mon_group_path( + cos, grp->name, NULL, buf, + sizeof(buf)); + if (stat(buf, &st) != 0) + continue; + + ret = resctrl_mon_read_counter( + cos, grp->name, l3id, + PQOS_MON_EVENT_L3_OCCUP, + &val); + if (ret != PQOS_RETVAL_OK) + goto mon_assign_exit; + + llc += val; + } while (++cos < max_cos); + } + if (llc > max_threshold_occupancy) + continue; + } + + resctrl_group = strdup(grp->name); + break; + } + } + +mon_assign_new: + /* Create new monitoring group */ + if (resctrl_group == NULL) { + char buf[32]; + + snprintf(buf, sizeof(buf), GROUP_NAME_PREFIX "%d-%u", + (int)getpid(), resctrl_mon_counter++); + + resctrl_group = strdup(buf); + if (resctrl_group == NULL) + LOG_DEBUG("Memory allocation failed\n"); + } + +mon_assign_exit: + if (cgrp != NULL) + free(cgrp); + return resctrl_group; +} + int resctrl_mon_start(struct pqos_mon_data *group) { char *resctrl_group = NULL; - char buf[128]; int ret = PQOS_RETVAL_OK; unsigned i; + const struct pqos_cpuinfo *cpu; ASSERT(group != NULL); ASSERT(group->tid_nr == 0 || group->tid_map != NULL); ASSERT(group->num_cores == 0 || group->cores != NULL); - /** - * Get resctrl monitoring group - */ - if (group->resctrl_mon_group == NULL) { - snprintf(buf, sizeof(buf), "%d-%u", (int)getpid(), - resctrl_mon_counter++); + _pqos_cap_get(NULL, &cpu); - resctrl_group = strdup(buf); - if (resctrl_group == NULL) { - LOG_DEBUG("Memory allocation failed\n"); + /* List l3ids */ + for (i = 0; i < group->num_cores; i++) { + struct pqos_mon_data_internal *intl = group->intl; + unsigned j; + const struct pqos_coreinfo *coreinfo = + pqos_cpu_get_core_info(cpu, group->cores[i]); + + if (coreinfo == NULL) { ret = PQOS_RETVAL_ERROR; goto resctrl_mon_start_exit; } - } else - resctrl_group = group->resctrl_mon_group; + for (j = 0; j < intl->resctrl.num_l3id; j++) + if (coreinfo->l3cat_id == intl->resctrl.l3id[j]) + break; + + if (j == intl->resctrl.num_l3id) { + intl->resctrl.l3id = + realloc(intl->resctrl.l3id, + sizeof(*intl->resctrl.l3id) * + (intl->resctrl.num_l3id + 1)); + if (intl->resctrl.l3id == NULL) { + ret = PQOS_RETVAL_ERROR; + goto resctrl_mon_start_exit; + } + intl->resctrl.l3id[intl->resctrl.num_l3id++] = + coreinfo->l3cat_id; + } + } + + /** + * Get resctrl monitoring group + */ + resctrl_group = resctrl_mon_assign(group); + if (resctrl_group == NULL) + return PQOS_RETVAL_ERROR; /** * Add pids to the resctrl group @@ -811,11 +1220,127 @@ goto resctrl_mon_start_exit; } - group->resctrl_mon_group = resctrl_group; + group->intl->resctrl.mon_group = resctrl_group; resctrl_mon_start_exit: - if (ret != PQOS_RETVAL_OK && group->resctrl_mon_group != resctrl_group) - free(resctrl_group); + if (ret != PQOS_RETVAL_OK) { + if (group->intl->resctrl.l3id != NULL) + free(group->intl->resctrl.l3id); + if (group->intl->resctrl.mon_group != resctrl_group) + free(resctrl_group); + } + + return ret; +} + +/** + * @brief Remove resctrl monitoring group + * + * @param [in] resctrl_group group name + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + */ +static int +resctrl_mon_delete(const char *resctrl_group) +{ + int ret; + unsigned max_cos; + unsigned cos = 0; + const struct pqos_cap *cap; + + _pqos_cap_get(&cap, NULL); + + ret = resctrl_alloc_get_grps_num(cap, &max_cos); + if (ret != PQOS_RETVAL_OK) + return ret; + + do { + char buf[128]; + + resctrl_mon_group_path(cos, resctrl_group, NULL, buf, + sizeof(buf)); + + ret = resctrl_mon_rmdir(buf); + if (ret != PQOS_RETVAL_OK) { + LOG_ERROR("Failed to remove resctrl " + "monitoring group\n"); + return PQOS_RETVAL_ERROR; + } + } while (++cos < max_cos); + + return PQOS_RETVAL_OK; +} + +/** + * @brief Check if resctrl group is shared between two mon groups + * + * @param [in] group monitoring structure + * @param [out] shared 1 if resctrl is shared + * + * @return Operation status + * @retval PQOS_RETVAL_OK on success + * @retval PQOS_RETVAL_ERROR if error occurs + */ +static int +resctrl_mon_shared(struct pqos_mon_data *group, unsigned *shared) +{ + unsigned max_cos; + unsigned cos; + int ret; + const struct pqos_cap *cap; + const struct pqos_cpuinfo *cpu; + const char *mon_group = group->intl->resctrl.mon_group; + + *shared = 0; + + if (group->num_pids > 0) + return PQOS_RETVAL_OK; + + _pqos_cap_get(&cap, &cpu); + + ret = resctrl_alloc_get_grps_num(cap, &max_cos); + if (ret != PQOS_RETVAL_OK) + return ret; + + cos = 0; + do { + char path[128]; + struct stat st; + struct resctrl_cpumask mask; + unsigned i; + + /* check if group exists */ + resctrl_mon_group_path(cos, mon_group, NULL, path, + sizeof(path)); + if (stat(path, &st) != 0) + continue; + + /* read assigned cores */ + ret = resctrl_mon_cpumask_read(cos, mon_group, &mask); + if (ret != PQOS_RETVAL_OK) + return ret; + + /* check if cores overlap */ + for (i = 0; i < cpu->num_cores; i++) { + const unsigned lcore = cpu->cores[i].lcore; + + if (resctrl_cpumask_get(lcore, &mask)) { + unsigned j; + + *shared = 1; + for (j = 0; j < group->num_cores; j++) + if (group->cores[i] == lcore) { + *shared = 0; + break; + } + } + + if (*shared) + return PQOS_RETVAL_OK; + } + + } while (++cos < max_cos); return ret; } @@ -833,7 +1358,6 @@ { int ret; unsigned max_cos; - unsigned cos; unsigned i; const struct pqos_cap *cap; @@ -845,29 +1369,10 @@ if (ret != PQOS_RETVAL_OK) return ret; - if (group->resctrl_mon_group != NULL) { - cos = 0; - do { - char buf[128]; - - resctrl_mon_group_path(cos, group->resctrl_mon_group, - NULL, buf, sizeof(buf)); - - ret = resctrl_mon_rmdir(buf); - if (ret != PQOS_RETVAL_OK) { - LOG_ERROR("Failed to remove resctrl " - "monitoring group\n"); - goto resctrl_mon_stop_exit; - } - } while (++cos < max_cos); - - free(group->resctrl_mon_group); - group->resctrl_mon_group = NULL; - - } else if (group->num_pids > 0) { - /** - * Add pids to the default group - */ + /* + * Add pids back to the default group + */ + if (group->num_pids > 0) for (i = 0; i < group->tid_nr; i++) { const pid_t tid = group->tid_map[i]; @@ -883,8 +1388,58 @@ goto resctrl_mon_stop_exit; } - } else - return PQOS_RETVAL_PARAM; + /* + * Remove cores from mon group + */ + if (group->num_cores > 0) { + const char *mon_group = group->intl->resctrl.mon_group; + char path[128]; + struct stat st; + unsigned cos = 0; + + do { + struct resctrl_cpumask cpumask; + + resctrl_mon_group_path(cos, mon_group, NULL, path, + sizeof(path)); + if (stat(path, &st) != 0) + continue; + + ret = + resctrl_mon_cpumask_read(cos, mon_group, &cpumask); + if (ret != PQOS_RETVAL_OK) + goto resctrl_mon_stop_exit; + + for (i = 0; i < group->num_cores; i++) { + const unsigned core = group->cores[i]; + + resctrl_cpumask_unset(core, &cpumask); + } + + ret = + resctrl_mon_cpumask_write(cos, mon_group, &cpumask); + if (ret != PQOS_RETVAL_OK) + goto resctrl_mon_stop_exit; + } while (++cos < max_cos); + } + + if (group->intl->resctrl.mon_group != NULL) { + unsigned shared; + + ret = resctrl_mon_shared(group, &shared); + if (ret != PQOS_RETVAL_OK) + goto resctrl_mon_stop_exit; + + if (!shared) { + ret = + resctrl_mon_delete(group->intl->resctrl.mon_group); + if (ret != PQOS_RETVAL_OK) + goto resctrl_mon_stop_exit; + } + + free(group->intl->resctrl.mon_group); + group->intl->resctrl.mon_group = NULL; + } resctrl_mon_stop_exit: return ret; @@ -923,12 +1478,19 @@ unsigned max_cos; unsigned cos; int ret; + unsigned shared; const struct pqos_cap *cap; ASSERT(group != NULL); _pqos_cap_get(&cap, NULL); + ret = resctrl_mon_shared(group, &shared); + if (ret != PQOS_RETVAL_OK) + return ret; + if (shared) + return PQOS_RETVAL_OK; + ret = resctrl_alloc_get_grps_num(cap, &max_cos); if (ret != PQOS_RETVAL_OK) return ret; @@ -940,12 +1502,14 @@ uint64_t value; char buf[128]; - resctrl_mon_group_path(cos, group->resctrl_mon_group, NULL, buf, - sizeof(buf)); + resctrl_mon_group_path(cos, group->intl->resctrl.mon_group, + NULL, buf, sizeof(buf)); if (stat(buf, &st) != 0) continue; - ret = resctrl_mon_empty(cos, group->resctrl_mon_group, &empty); + ret = resctrl_mon_empty(cos, group->intl->resctrl.mon_group, + group->intl->resctrl.l3id, + group->intl->resctrl.num_l3id, &empty); if (ret != PQOS_RETVAL_OK) return ret; @@ -955,20 +1519,24 @@ /* store counter values */ if (supported_events & PQOS_MON_EVENT_LMEM_BW) { ret = resctrl_mon_read_counters( - cos, group->resctrl_mon_group, + cos, group->intl->resctrl.mon_group, + group->intl->resctrl.l3id, + group->intl->resctrl.num_l3id, PQOS_MON_EVENT_LMEM_BW, &value); if (ret != PQOS_RETVAL_OK) return ret; - group->resctrl_values_storage.mbm_local += value; + group->intl->resctrl.values_storage.mbm_local += value; } if (supported_events & PQOS_MON_EVENT_TMEM_BW) { ret = resctrl_mon_read_counters( - cos, group->resctrl_mon_group, + cos, group->intl->resctrl.mon_group, + group->intl->resctrl.l3id, + group->intl->resctrl.num_l3id, PQOS_MON_EVENT_TMEM_BW, &value); if (ret != PQOS_RETVAL_OK) return ret; - group->resctrl_values_storage.mbm_total += value; + group->intl->resctrl.values_storage.mbm_total += value; } ret = resctrl_mon_rmdir(buf); @@ -1021,7 +1589,7 @@ */ for (i = 0; i < group->num_cores; i++) { ret = resctrl_mon_assoc_restore(group->cores[i], - group->resctrl_mon_group); + group->intl->resctrl.mon_group); if (ret != PQOS_RETVAL_OK) goto resctrl_mon_poll_exit; } @@ -1033,13 +1601,15 @@ struct stat st; char buf[128]; - resctrl_mon_group_path(cos, group->resctrl_mon_group, NULL, buf, - sizeof(buf)); + resctrl_mon_group_path(cos, group->intl->resctrl.mon_group, + NULL, buf, sizeof(buf)); if (stat(buf, &st) != 0) continue; - ret = resctrl_mon_read_counters(cos, group->resctrl_mon_group, - event, &val); + ret = resctrl_mon_read_counters( + cos, group->intl->resctrl.mon_group, + group->intl->resctrl.l3id, group->intl->resctrl.num_l3id, + event, &val); if (ret != PQOS_RETVAL_OK) goto resctrl_mon_poll_exit; @@ -1057,14 +1627,14 @@ case PQOS_MON_EVENT_LMEM_BW: old_value = group->values.mbm_local; group->values.mbm_local = - value + group->resctrl_values_storage.mbm_local; + value + group->intl->resctrl.values_storage.mbm_local; group->values.mbm_local_delta = get_delta(old_value, group->values.mbm_local); break; case PQOS_MON_EVENT_TMEM_BW: old_value = group->values.mbm_total; group->values.mbm_total = - value + group->resctrl_values_storage.mbm_total; + value + group->intl->resctrl.values_storage.mbm_total; group->values.mbm_total_delta = get_delta(old_value, group->values.mbm_total); break; @@ -1124,12 +1694,12 @@ ret = resctrl_mon_rmdir(path); if (ret != PQOS_RETVAL_OK) { - free(namelist); + free_scandir(namelist, num_groups); return ret; } } - free(namelist); + free_scandir(namelist, num_groups); } while (++cos < grps); return ret; @@ -1171,7 +1741,7 @@ /* check content of mon_groups directory */ files_count = scandir(path, &mon_group_files, filter, NULL); - free(mon_group_files); + free_scandir(mon_group_files, files_count); if (files_count < 0) { LOG_ERROR("Could not scan %s directory!\n", path); diff -Nru intel-cmt-cat-3.2/lib/resctrl_monitoring.h intel-cmt-cat-4.0/lib/resctrl_monitoring.h --- intel-cmt-cat-3.2/lib/resctrl_monitoring.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_monitoring.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/resctrl_schemata.c intel-cmt-cat-4.0/lib/resctrl_schemata.c --- intel-cmt-cat-3.2/lib/resctrl_schemata.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_schemata.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/resctrl_schemata.h intel-cmt-cat-4.0/lib/resctrl_schemata.h --- intel-cmt-cat-3.2/lib/resctrl_schemata.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_schemata.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/resctrl_utils.c intel-cmt-cat-4.0/lib/resctrl_utils.c --- intel-cmt-cat-3.2/lib/resctrl_utils.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_utils.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/resctrl_utils.h intel-cmt-cat-4.0/lib/resctrl_utils.h --- intel-cmt-cat-3.2/lib/resctrl_utils.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/resctrl_utils.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/lib/types.h intel-cmt-cat-4.0/lib/types.h --- intel-cmt-cat-3.2/lib/types.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/types.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +48,7 @@ #endif #ifndef DIM -#define DIM(x) (sizeof(x)/sizeof(x[0])) +#define DIM(x) (sizeof(x) / sizeof(x[0])) #endif #define UNUSED_PARAM(x) (void)(x) diff -Nru intel-cmt-cat-3.2/lib/utils.c intel-cmt-cat-4.0/lib/utils.c --- intel-cmt-cat-3.2/lib/utils.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/utils.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,13 +40,11 @@ */ #include #include -#ifdef __linux__ -#include /* alloca() */ -#endif /* __linux__ */ #include "pqos.h" #include "types.h" #include "utils.h" +#include "cpuinfo.h" #define TOPO_OBJ_SOCKET 0 #define TOPO_OBJ_L2_CLUSTER 2 @@ -54,7 +52,6 @@ static int m_interface = PQOS_INTER_MSR; - int _pqos_utils_init(int interface) { @@ -67,84 +64,81 @@ } unsigned * -pqos_cpu_get_mba_ids(const struct pqos_cpuinfo *cpu, - unsigned *count) +pqos_cpu_get_mba_ids(const struct pqos_cpuinfo *cpu, unsigned *count) { - unsigned mba_id_count = 0, i = 0; - unsigned *mba_ids = NULL; + unsigned mba_id_count = 0, i = 0; + unsigned *mba_ids = NULL; + + ASSERT(cpu != NULL); + ASSERT(count != NULL); + if (cpu == NULL || count == NULL) + return NULL; + + mba_ids = (unsigned *)malloc(sizeof(mba_ids[0]) * cpu->num_cores); + if (mba_ids == NULL) + return NULL; - ASSERT(cpu != NULL); - ASSERT(count != NULL); - if (cpu == NULL || count == NULL) - return NULL; - - mba_ids = (unsigned *) malloc(sizeof(mba_ids[0]) * cpu->num_cores); - if (mba_ids == NULL) - return NULL; - - for (i = 0; i < cpu->num_cores; i++) { - unsigned j = 0; - - /** - * Check if this mba id is already on the \a mbas list - */ - for (j = 0; j < mba_id_count && mba_id_count > 0; j++) - if (cpu->cores[i].mba_id == mba_ids[j]) - break; - - if (j >= mba_id_count || mba_id_count == 0) { - /** - * This mba_id wasn't reported before - */ - mba_ids[mba_id_count++] = cpu->cores[i].mba_id; - } - } + for (i = 0; i < cpu->num_cores; i++) { + unsigned j = 0; + + /** + * Check if this mba id is already on the \a mbas list + */ + for (j = 0; j < mba_id_count && mba_id_count > 0; j++) + if (cpu->cores[i].mba_id == mba_ids[j]) + break; - *count = mba_id_count; - return mba_ids; + if (j >= mba_id_count || mba_id_count == 0) { + /** + * This mba_id wasn't reported before + */ + mba_ids[mba_id_count++] = cpu->cores[i].mba_id; + } + } + + *count = mba_id_count; + return mba_ids; } unsigned * -pqos_cpu_get_l3cat_ids(const struct pqos_cpuinfo *cpu, - unsigned *count) +pqos_cpu_get_l3cat_ids(const struct pqos_cpuinfo *cpu, unsigned *count) { - unsigned l3cat_count = 0, i = 0; - unsigned *l3cat_ids = NULL; + unsigned l3cat_count = 0, i = 0; + unsigned *l3cat_ids = NULL; - ASSERT(cpu != NULL); - ASSERT(count != NULL); - if (cpu == NULL || count == NULL) - return NULL; - - l3cat_ids = (unsigned *) malloc(sizeof(l3cat_ids[0]) * cpu->num_cores); - if (l3cat_ids == NULL) - return NULL; - - for (i = 0; i < cpu->num_cores; i++) { - unsigned j = 0; - - /** - * Check if this l3cat id is already on the \a l3cat_ids list - */ - for (j = 0; j < l3cat_count && l3cat_count > 0; j++) - if (cpu->cores[i].l3cat_id == l3cat_ids[j]) - break; - - if (j >= l3cat_count || l3cat_count == 0) { - /** - * This l3cat_id wasn't reported before - */ - l3cat_ids[l3cat_count++] = cpu->cores[i].l3cat_id; - } - } + ASSERT(cpu != NULL); + ASSERT(count != NULL); + if (cpu == NULL || count == NULL) + return NULL; - *count = l3cat_count; - return l3cat_ids; + l3cat_ids = (unsigned *)malloc(sizeof(l3cat_ids[0]) * cpu->num_cores); + if (l3cat_ids == NULL) + return NULL; + + for (i = 0; i < cpu->num_cores; i++) { + unsigned j = 0; + + /** + * Check if this l3cat id is already on the \a l3cat_ids list + */ + for (j = 0; j < l3cat_count && l3cat_count > 0; j++) + if (cpu->cores[i].l3cat_id == l3cat_ids[j]) + break; + + if (j >= l3cat_count || l3cat_count == 0) { + /** + * This l3cat_id wasn't reported before + */ + l3cat_ids[l3cat_count++] = cpu->cores[i].l3cat_id; + } + } + + *count = l3cat_count; + return l3cat_ids; } unsigned * -pqos_cpu_get_sockets(const struct pqos_cpuinfo *cpu, - unsigned *count) +pqos_cpu_get_sockets(const struct pqos_cpuinfo *cpu, unsigned *count) { unsigned scount = 0, i = 0; unsigned *sockets = NULL; @@ -154,7 +148,7 @@ if (cpu == NULL || count == NULL) return NULL; - sockets = (unsigned *) malloc(sizeof(sockets[0]) * cpu->num_cores); + sockets = (unsigned *)malloc(sizeof(sockets[0]) * cpu->num_cores); if (sockets == NULL) return NULL; @@ -181,8 +175,7 @@ } unsigned * -pqos_cpu_get_l2ids(const struct pqos_cpuinfo *cpu, - unsigned *count) +pqos_cpu_get_l2ids(const struct pqos_cpuinfo *cpu, unsigned *count) { unsigned l2count = 0, i = 0; unsigned *l2ids = NULL; @@ -192,7 +185,7 @@ if (cpu == NULL || count == NULL) return NULL; - l2ids = (unsigned *) malloc(sizeof(l2ids[0]) * cpu->num_cores); + l2ids = (unsigned *)malloc(sizeof(l2ids[0]) * cpu->num_cores); if (l2ids == NULL) return NULL; @@ -246,7 +239,7 @@ if (cpu == NULL || count == NULL) return NULL; - core_list = (unsigned *) malloc(cpu->num_cores * sizeof(core_list[0])); + core_list = (unsigned *)malloc(cpu->num_cores * sizeof(core_list[0])); if (core_list == NULL) return NULL; @@ -268,7 +261,8 @@ } unsigned * -pqos_cpu_get_cores_l3id(const struct pqos_cpuinfo *cpu, const unsigned l3_id, +pqos_cpu_get_cores_l3id(const struct pqos_cpuinfo *cpu, + const unsigned l3_id, unsigned *count) { return __get_cores_per_topology_obj(cpu, TOPO_OBJ_L3_CLUSTER, l3_id, @@ -289,7 +283,7 @@ if (cpu == NULL || count == NULL) return NULL; - cores = (unsigned *) malloc(cpu->num_cores * sizeof(cores[0])); + cores = (unsigned *)malloc(cpu->num_cores * sizeof(cores[0])); if (cores == NULL) return NULL; @@ -347,46 +341,46 @@ int pqos_cpu_get_one_by_l3cat_id(const struct pqos_cpuinfo *cpu, - const unsigned l3cat_id, - unsigned *lcore) + const unsigned l3cat_id, + unsigned *lcore) { - unsigned i = 0; + unsigned i = 0; - ASSERT(cpu != NULL); - ASSERT(lcore != NULL); + ASSERT(cpu != NULL); + ASSERT(lcore != NULL); - if (cpu == NULL || lcore == NULL) - return PQOS_RETVAL_PARAM; + if (cpu == NULL || lcore == NULL) + return PQOS_RETVAL_PARAM; - for (i = 0; i < cpu->num_cores; i++) - if (cpu->cores[i].l3cat_id == l3cat_id) { - *lcore = cpu->cores[i].lcore; - return PQOS_RETVAL_OK; - } + for (i = 0; i < cpu->num_cores; i++) + if (cpu->cores[i].l3cat_id == l3cat_id) { + *lcore = cpu->cores[i].lcore; + return PQOS_RETVAL_OK; + } - return PQOS_RETVAL_ERROR; + return PQOS_RETVAL_ERROR; } int pqos_cpu_get_one_by_mba_id(const struct pqos_cpuinfo *cpu, - const unsigned mba_id, - unsigned *lcore) + const unsigned mba_id, + unsigned *lcore) { - unsigned i = 0; + unsigned i = 0; - ASSERT(cpu != NULL); - ASSERT(lcore != NULL); + ASSERT(cpu != NULL); + ASSERT(lcore != NULL); - if (cpu == NULL || lcore == NULL) - return PQOS_RETVAL_PARAM; + if (cpu == NULL || lcore == NULL) + return PQOS_RETVAL_PARAM; - for (i = 0; i < cpu->num_cores; i++) - if (cpu->cores[i].mba_id == mba_id) { - *lcore = cpu->cores[i].lcore; - return PQOS_RETVAL_OK; - } + for (i = 0; i < cpu->num_cores; i++) + if (cpu->cores[i].mba_id == mba_id) { + *lcore = cpu->cores[i].lcore; + return PQOS_RETVAL_OK; + } - return PQOS_RETVAL_ERROR; + return PQOS_RETVAL_ERROR; } int @@ -412,8 +406,7 @@ } int -pqos_cpu_check_core(const struct pqos_cpuinfo *cpu, - const unsigned lcore) +pqos_cpu_check_core(const struct pqos_cpuinfo *cpu, const unsigned lcore) { unsigned i = 0; @@ -530,8 +523,7 @@ } int -pqos_l3ca_get_cos_num(const struct pqos_cap *cap, - unsigned *cos_num) +pqos_l3ca_get_cos_num(const struct pqos_cap *cap, unsigned *cos_num) { const struct pqos_capability *item = NULL; int ret = PQOS_RETVAL_OK; @@ -542,7 +534,7 @@ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L3CA, &item); if (ret != PQOS_RETVAL_OK) - return ret; /**< no L3CA capability */ + return ret; /**< no L3CA capability */ ASSERT(item != NULL); *cos_num = item->u.l3ca->num_classes; @@ -550,8 +542,7 @@ } int -pqos_l2ca_get_cos_num(const struct pqos_cap *cap, - unsigned *cos_num) +pqos_l2ca_get_cos_num(const struct pqos_cap *cap, unsigned *cos_num) { const struct pqos_capability *item = NULL; int ret = PQOS_RETVAL_OK; @@ -562,7 +553,7 @@ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L2CA, &item); if (ret != PQOS_RETVAL_OK) - return ret; /**< no L2CA capability */ + return ret; /**< no L2CA capability */ ASSERT(item != NULL); *cos_num = item->u.l2ca->num_classes; @@ -570,8 +561,7 @@ } int -pqos_mba_get_cos_num(const struct pqos_cap *cap, - unsigned *cos_num) +pqos_mba_get_cos_num(const struct pqos_cap *cap, unsigned *cos_num) { const struct pqos_capability *item = NULL; int ret = PQOS_RETVAL_OK; @@ -582,7 +572,7 @@ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &item); if (ret != PQOS_RETVAL_OK) - return ret; /**< no MBA capability */ + return ret; /**< no MBA capability */ ASSERT(item != NULL); *cos_num = item->u.mba->num_classes; @@ -603,7 +593,7 @@ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L3CA, &item); if (ret != PQOS_RETVAL_OK) - return ret; /**< no L3CA capability */ + return ret; /**< no L3CA capability */ ASSERT(item != NULL); if (cdp_supported != NULL) @@ -629,7 +619,7 @@ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_L2CA, &l2ca); if (ret != PQOS_RETVAL_OK) - return ret; /**< no L2CA capability */ + return ret; /**< no L2CA capability */ ASSERT(l2ca != NULL); if (cdp_supported != NULL) @@ -655,7 +645,7 @@ ret = pqos_cap_get_type(cap, PQOS_CAP_TYPE_MBA, &mba_cap); if (ret != PQOS_RETVAL_OK) - return ret; /**< no MBA capability */ + return ret; /**< no MBA capability */ ASSERT(mba_cap != NULL); if (ctrl_supported != NULL) @@ -666,3 +656,9 @@ return PQOS_RETVAL_OK; } + +enum pqos_vendor +pqos_get_vendor(const struct pqos_cpuinfo *m_cpu) +{ + return m_cpu->vendor; +} diff -Nru intel-cmt-cat-3.2/lib/utils.h intel-cmt-cat-4.0/lib/utils.h --- intel-cmt-cat-3.2/lib/utils.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/lib/utils.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,6 @@ extern "C" { #endif - /** * @brief Initializes utils module * @@ -54,10 +53,8 @@ */ int _pqos_utils_init(int interface); - #ifdef __cplusplus } #endif #endif /* __PQOS_UTULS_H__ */ - diff -Nru intel-cmt-cat-3.2/LICENSE intel-cmt-cat-4.0/LICENSE --- intel-cmt-cat-3.2/LICENSE 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/LICENSE 2020-06-19 10:42:55.000000000 +0000 @@ -1,6 +1,6 @@ BSD LICENSE -Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +Copyright(c) 2014-2020 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/Makefile intel-cmt-cat-4.0/Makefile --- intel-cmt-cat-3.2/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/alloc.c intel-cmt-cat-4.0/pqos/alloc.c --- intel-cmt-cat-3.2/pqos/alloc.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/alloc.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -191,6 +191,8 @@ unsigned j, num_ca; struct pqos_l3ca ca, sock_l3ca[PQOS_MAX_L3CA_COS]; + memset(&ca, 0, sizeof(ca)); + /* get current L3 definitions for this socket */ ret = pqos_l3ca_get(sock_ids[i], DIM(sock_l3ca), &num_ca, sock_l3ca); @@ -285,6 +287,8 @@ unsigned j, num_ca; struct pqos_l2ca ca, cluster_l2ca[PQOS_MAX_L2CA_COS]; + memset(&ca, 0, sizeof(ca)); + /* get current L2 definitions for this cluster */ ret = pqos_l2ca_get(l2_ids[i], DIM(cluster_l2ca), &num_ca, cluster_l2ca); @@ -943,12 +947,16 @@ static void print_per_socket_config(const struct pqos_capability *cap_l3ca, const struct pqos_capability *cap_mba, + const struct pqos_cpuinfo *cpu_info, const unsigned sock_count, const unsigned *sockets) { int ret; unsigned i; + if (cpu_info == NULL || sockets == NULL) + return; + if (cap_l3ca == NULL && cap_mba == NULL) return; @@ -988,8 +996,11 @@ unit = " MBps"; available = ""; } else { - unit = "%"; available = " available"; + if (cpu_info->vendor == PQOS_VENDOR_AMD) + unit = ""; + else + unit = "%"; } ret = pqos_mba_get(sockets[i], mba->num_classes, @@ -1070,7 +1081,8 @@ return; } - print_per_socket_config(cap_l3ca, cap_mba, sock_count, sockets); + print_per_socket_config(cap_l3ca, cap_mba, cpu_info, sock_count, + sockets); if (cap_l2ca != NULL) { /* Print L2 CAT class definitions per L2 cluster */ diff -Nru intel-cmt-cat-3.2/pqos/alloc.h intel-cmt-cat-4.0/pqos/alloc.h --- intel-cmt-cat-3.2/pqos/alloc.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/alloc.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/cap.c intel-cmt-cat-4.0/pqos/cap.c --- intel-cmt-cat-3.2/pqos/cap.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/cap.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,10 +47,9 @@ #include "main.h" #include "cap.h" -#define BUFFER_SIZE 256 +#define BUFFER_SIZE 512 #define NON_VERBOSE 0 - /** * @brief Print line with indentation * @@ -166,33 +165,41 @@ if (buffer == NULL) continue; - if (verbose && - (monitor->scale_factor != 0 || monitor->max_rmid != 0)) - snprintf(buffer + strlen(buffer), - BUFFER_SIZE - strlen(buffer), - "%*s%s: scale factor %u, max_rmid %u\n", - indent + 8, "", - get_mon_event_name(monitor->type), - monitor->scale_factor, monitor->max_rmid); - else - snprintf(buffer + strlen(buffer), - BUFFER_SIZE - strlen(buffer), - "%*s%s\n", - indent + 8, "", - get_mon_event_name(monitor->type)); + snprintf(buffer + strlen(buffer), BUFFER_SIZE - strlen(buffer), + "%*s%s\n", indent + 8, "", + get_mon_event_name(monitor->type)); + + if (verbose) { + if (monitor->scale_factor != 0) + snprintf(buffer + strlen(buffer), + BUFFER_SIZE - strlen(buffer), + "%*s scale factor: %u\n", indent + 12, + "", monitor->scale_factor); + if (monitor->max_rmid != 0) + snprintf(buffer + strlen(buffer), + BUFFER_SIZE - strlen(buffer), + "%*s max rmid: %u\n", indent + 12, "", + monitor->max_rmid); + if (monitor->counter_length != 0) + snprintf(buffer + strlen(buffer), + BUFFER_SIZE - strlen(buffer), + "%*s counter length: %ub\n", + indent + 12, "", + monitor->counter_length); + } } printf_indent(indent, "Monitoring\n"); if (strlen(buffer_cache) > 0) { printf_indent(indent + 4, - "Cache Monitoring Technology (CMT) events:\n"); + "Cache Monitoring Technology (CMT) events:\n"); printf("%s", buffer_cache); } if (strlen(buffer_memory) > 0) { printf_indent(indent + 4, - "Memory Bandwidth Monitoring (MBM) events:\n"); + "Memory Bandwidth Monitoring (MBM) events:\n"); printf("%s", buffer_memory); } @@ -220,8 +227,8 @@ printf_indent(indent, "L3 CAT\n"); printf_indent(indent + 4, "CDP: %s\n", - l3ca->cdp ? (l3ca->cdp_on ? "enabled" : "disabled") : - "unsupported"); + l3ca->cdp ? (l3ca->cdp_on ? "enabled" : "disabled") + : "unsupported"); printf_indent(indent + 4, "Num COS: %u\n", l3ca->num_classes); if (!verbose) @@ -229,7 +236,7 @@ printf_indent(indent + 4, "Way size: %u bytes\n", l3ca->way_size); printf_indent(indent + 4, "Ways contention bit-mask: 0x%lx\n", - l3ca->way_contention); + l3ca->way_contention); if (pqos_l3ca_get_min_cbm_bits(&min_cbm_bits) != PQOS_RETVAL_OK) printf_indent(indent + 4, "Min CBM bits: unavailable\n"); else @@ -256,8 +263,8 @@ printf_indent(indent, "L2 CAT\n"); printf_indent(indent + 4, "CDP: %s\n", - l2ca->cdp ? (l2ca->cdp_on ? "enabled" : "disabled") : - "unsupported"); + l2ca->cdp ? (l2ca->cdp_on ? "enabled" : "disabled") + : "unsupported"); printf_indent(indent + 4, "Num COS: %u\n", l2ca->num_classes); if (!verbose) @@ -265,7 +272,7 @@ printf_indent(indent + 4, "Way size: %u bytes\n", l2ca->way_size); printf_indent(indent + 4, "Ways contention bit-mask: 0x%lx\n", - l2ca->way_contention); + l2ca->way_contention); if (pqos_l2ca_get_min_cbm_bits(&min_cbm_bits) != PQOS_RETVAL_OK) printf_indent(indent + 4, "Min CBM bits: unavailable\n"); else @@ -273,7 +280,6 @@ printf_indent(indent + 4, "Max CBM bits: %u\n", l2ca->num_ways); } - /** * @brief Print MBA capabilities * @@ -311,7 +317,7 @@ printf_indent(indent + 4, "Granularity: %u\n", mba->throttle_step); printf_indent(indent + 4, "Min B/W: %u\n", 100 - mba->throttle_max); printf_indent(indent + 4, "Type: %s\n", - mba->is_linear ? "linear" : "nonlinear"); + mba->is_linear ? "linear" : "nonlinear"); } /** @@ -330,8 +336,8 @@ const struct pqos_capability *cap_mba, const int verbose) { - if (cap_mon == NULL && cap_l3ca == NULL && - cap_l2ca == NULL && cap_mba == NULL) + if (cap_mon == NULL && cap_l3ca == NULL && cap_l2ca == NULL && + cap_mba == NULL) return; /** diff -Nru intel-cmt-cat-3.2/pqos/cap.h intel-cmt-cat-4.0/pqos/cap.h --- intel-cmt-cat-3.2/pqos/cap.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/cap.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2017-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,7 +58,6 @@ const struct pqos_cpuinfo *cpu, const int verbose); - #ifdef __cplusplus } #endif diff -Nru intel-cmt-cat-3.2/pqos/common.c intel-cmt-cat-4.0/pqos/common.c --- intel-cmt-cat-3.2/pqos/common.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/common.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,106 +32,87 @@ * */ -#include +#include +#include #include -#include -#include -#include #include -#include "pqos.h" - #include "common.h" - -/** - * @brief Checks if a path to a file contains any symbolic links. - * - * @param [in] name a path to a file - * - * @return Operation status - * @retval PQOS_RETVAL_OK if the path exists and does not contain any - * symbolic links. - */ -static int -check_symlink(const char *name) -{ - int fd; - int oflag; - char *dir = strdup(name); - char *path = dir; - - if (dir == NULL) - return PQOS_RETVAL_ERROR; - - oflag = O_RDONLY; - - do { - fd = open(path, oflag | O_NOFOLLOW); - if (fd == -1) { - if (errno == ELOOP) - printf("File %s is a symlink\n", path); - - free(dir); - return PQOS_RETVAL_ERROR; - } - - oflag = O_RDONLY | O_DIRECTORY; - path = dirname(path); - - if (fd != -1) - close(fd); - } while ((strcmp(path, ".") != 0) && (strcmp(path, "/") != 0)); - - free(dir); - return PQOS_RETVAL_OK; -} - FILE * -fopen_check_symlink(const char *name, const char *mode) +pqos_fopen(const char *name, const char *mode) { int fd; - int ret; - char *dir; - char *file_name; - - /* If the file will be created, check a parent directory for symlinks */ - if (mode != NULL && (mode[0] == 'w' || mode[0] == 'a')) { - file_name = strdup(name); - - if (file_name == NULL) - return NULL; - - fd = open(file_name, O_RDONLY); - - if (fd == -1) { - dir = dirname(file_name); - ret = check_symlink(dir); - } else { - ret = check_symlink(name); - close(fd); - } - - free(file_name); - } else - ret = check_symlink(name); + FILE *stream = NULL; + struct stat lstat_val; + struct stat fstat_val; + + stream = fopen(name, mode); + if (stream == NULL) + return stream; + + fd = fileno(stream); + if (fd == -1) + goto pqos_fopen_error; + + /* collect any link info about the file */ + if (lstat(name, &lstat_val) == -1) + goto pqos_fopen_error; + + /* collect info about the opened file */ + if (fstat(fd, &fstat_val) == -1) + goto pqos_fopen_error; + + /* we should not have followed a symbolic link */ + if (lstat_val.st_mode != fstat_val.st_mode || + lstat_val.st_ino != fstat_val.st_ino || + lstat_val.st_dev != fstat_val.st_dev) { + printf("File %s is a symlink\n", name); + goto pqos_fopen_error; + } + + return stream; - if (ret != PQOS_RETVAL_OK) - return NULL; +pqos_fopen_error: + if (stream != NULL) + fclose(stream); - return fopen(name, mode); + return NULL; } int -open_check_symlink(const char *pathname, int flags, mode_t mode) +pqos_open(const char *pathname, int flags, mode_t mode) { - int ret; + int fd; + struct stat lstat_val; + struct stat fstat_val; - ret = check_symlink(pathname); - if (ret != PQOS_RETVAL_OK) { - errno = EACCES; - return -1; + /* open the file */ + fd = open(pathname, flags, mode); + if (fd == -1) + return fd; + + /* collect any link info about the file */ + if (lstat(pathname, &lstat_val) == -1) + goto pqos_open_error; + + /* collect info about the opened file */ + if (fstat(fd, &fstat_val) == -1) + goto pqos_open_error; + + /* we should not have followed a symbolic link */ + if (lstat_val.st_mode != fstat_val.st_mode || + lstat_val.st_ino != fstat_val.st_ino || + lstat_val.st_dev != fstat_val.st_dev) { + printf("File %s is a symlink\n", pathname); + goto pqos_open_error; } - return open(pathname, flags, mode); + return fd; + +pqos_open_error: + if (fd != -1) + close(fd); + + return -1; } diff -Nru intel-cmt-cat-3.2/pqos/common.h intel-cmt-cat-4.0/pqos/common.h --- intel-cmt-cat-3.2/pqos/common.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/common.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,8 +56,7 @@ * @retval A valid pointer to a file or NULL on error (e.g. when the path * contains any symbolic links). */ -FILE * -fopen_check_symlink(const char *name, const char *mode); +FILE * pqos_fopen(const char *name, const char *mode); /** * @brief Wrapper around open() that additionally checks if a given path @@ -71,8 +70,7 @@ * @retval A valid file descriptor or -1 on error (e.g. when the path * contains any symbolic links). */ -int -open_check_symlink(const char *pathname, int flags, mode_t mode); +int pqos_open(const char *pathname, int flags, mode_t mode); #ifdef __cplusplus } diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_config_cdp.cfg intel-cmt-cat-4.0/pqos/configs/alloc_config_cdp.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_config_cdp.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_config_cdp.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_reset_cat.cfg intel-cmt-cat-4.0/pqos/configs/alloc_reset_cat.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_reset_cat.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_reset_cat.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_select_clos.cfg intel-cmt-cat-4.0/pqos/configs/alloc_select_clos.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_select_clos.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_select_clos.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_11LLC_ways_cdp.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_11LLC_ways_cdp.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_11LLC_ways_cdp.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_11LLC_ways_cdp.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2017-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2017-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_11LLC_ways.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_11LLC_ways.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_11LLC_ways.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_11LLC_ways.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2017-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2017-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_12LLC_ways_cdp.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_12LLC_ways_cdp.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_12LLC_ways_cdp.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_12LLC_ways_cdp.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_12LLC_ways.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_12LLC_ways.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_12LLC_ways.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_12LLC_ways.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_20LLC_ways_cdp.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_20LLC_ways_cdp.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_20LLC_ways_cdp.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_20LLC_ways_cdp.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_20LLC_ways.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_20LLC_ways.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_clos_20LLC_ways.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_clos_20LLC_ways.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -6,7 +6,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_set_core_assoc.cfg intel-cmt-cat-4.0/pqos/configs/alloc_set_core_assoc.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_set_core_assoc.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_set_core_assoc.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/alloc_show_verbose.cfg intel-cmt-cat-4.0/pqos/configs/alloc_show_verbose.cfg --- intel-cmt-cat-3.2/pqos/configs/alloc_show_verbose.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/alloc_show_verbose.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/mon_llc_core_text.cfg intel-cmt-cat-4.0/pqos/configs/mon_llc_core_text.cfg --- intel-cmt-cat-3.2/pqos/configs/mon_llc_core_text.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/mon_llc_core_text.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/mon_llc_core_xml_file.cfg intel-cmt-cat-4.0/pqos/configs/mon_llc_core_xml_file.cfg --- intel-cmt-cat-3.2/pqos/configs/mon_llc_core_xml_file.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/mon_llc_core_xml_file.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -8,7 +8,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/mon_llc_pid_text.cfg intel-cmt-cat-4.0/pqos/configs/mon_llc_pid_text.cfg --- intel-cmt-cat-3.2/pqos/configs/mon_llc_pid_text.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/mon_llc_pid_text.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/mon_llc_pid_xml_file.cfg intel-cmt-cat-4.0/pqos/configs/mon_llc_pid_xml_file.cfg --- intel-cmt-cat-3.2/pqos/configs/mon_llc_pid_xml_file.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/mon_llc_pid_xml_file.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/mon_mbl_core_text.cfg intel-cmt-cat-4.0/pqos/configs/mon_mbl_core_text.cfg --- intel-cmt-cat-3.2/pqos/configs/mon_mbl_core_text.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/mon_mbl_core_text.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/mon_mbr_core_interval.cfg intel-cmt-cat-4.0/pqos/configs/mon_mbr_core_interval.cfg --- intel-cmt-cat-3.2/pqos/configs/mon_mbr_core_interval.cfg 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/mon_mbr_core_interval.cfg 2020-06-19 10:42:55.000000000 +0000 @@ -7,7 +7,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2015-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2015-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/configs/README intel-cmt-cat-4.0/pqos/configs/README --- intel-cmt-cat-3.2/pqos/configs/README 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/configs/README 2020-06-19 10:42:55.000000000 +0000 @@ -130,6 +130,7 @@ - Last Level Cache Occupancy (llc) - Local Memory Bandwidth (mbl) - Remote Memory Bandwidth (mbr) +- Total Memory Bandwidth (mbt) Description: Selects core(s) and events to be monitored diff -Nru intel-cmt-cat-3.2/pqos/main.c intel-cmt-cat-4.0/pqos/main.c --- intel-cmt-cat-3.2/pqos/main.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/main.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -570,7 +570,7 @@ FILE *fp = NULL; char cb[256]; - fp = fopen_check_symlink(fname, "r"); + fp = pqos_fopen(fname, "r"); if (fp == NULL) parse_error(fname, "cannot open configuration file!"); @@ -641,6 +641,7 @@ #ifdef PQOS_RMID_CUSTOM " %s [--rmid=RMIDCORES]\n" #endif + " %s [--disable-mon-ipc] [--disable-mon-llc_miss]" " [-t SECONDS] [--mon-time=SECONDS]\n" " [-i N] [--mon-interval=N]\n" " [-T] [--mon-top]\n" @@ -700,6 +701,10 @@ " RMIDCORES format is 'RMID_NUMBER=CORE_LIST'\n" " Example \"10=0,2,4;11=1,3,5 \"\n" #endif + " --disable-mon-ipc\n" + " Disable IPC monitoring\n" + " --disable-mon-llc_miss\n" + " Disable LLC misses monitoring\n" " -p [EVTPIDS], --mon-pid[=EVTPIDS]\n" " select top 10 most active (CPU utilizing) process ids to monitor\n" " or select process ids and events to monitor.\n" @@ -747,7 +752,7 @@ #ifdef PQOS_RMID_CUSTOM m_cmd_name, #endif - m_cmd_name, m_cmd_name, m_cmd_name, m_cmd_name); + m_cmd_name, m_cmd_name, m_cmd_name, m_cmd_name, m_cmd_name); if (is_long) printf("%s", help_printf_long); } @@ -769,34 +774,39 @@ #ifdef PQOS_RMID_CUSTOM #define OPTION_RMID 1000 #endif +#define OPTION_DISABLE_MON_IPC 1001 +#define OPTION_DISABLE_MON_LLC_MISS 1002 static struct option long_cmd_opts[] = { - {"help", no_argument, 0, 'h'}, - {"log-file", required_argument, 0, 'l'}, - {"config-file", required_argument, 0, 'f'}, - {"show", no_argument, 0, 's'}, - {"display", no_argument, 0, 'd'}, - {"display-verbose", no_argument, 0, 'D'}, - {"profile-list", no_argument, 0, 'H'}, - {"profile-set", required_argument, 0, 'c'}, - {"mon-interval", required_argument, 0, 'i'}, - {"mon-pid", required_argument, 0, 'p'}, - {"mon-core", required_argument, 0, 'm'}, - {"mon-time", required_argument, 0, 't'}, - {"mon-top", no_argument, 0, 'T'}, - {"mon-file", required_argument, 0, 'o'}, - {"mon-file-type", required_argument, 0, 'u'}, - {"mon-reset", no_argument, 0, 'r'}, - {"alloc-class", required_argument, 0, 'e'}, - {"alloc-reset", required_argument, 0, 'R'}, - {"alloc-assoc", required_argument, 0, 'a'}, - {"verbose", no_argument, 0, 'v'}, - {"super-verbose", no_argument, 0, 'V'}, - {"iface-os", no_argument, 0, 'I'}, - {"percent-llc", no_argument, 0, 'P'}, - {"version", no_argument, 0, 'w'}, + {"help", no_argument, 0, 'h'}, + {"log-file", required_argument, 0, 'l'}, + {"config-file", required_argument, 0, 'f'}, + {"show", no_argument, 0, 's'}, + {"display", no_argument, 0, 'd'}, + {"display-verbose", no_argument, 0, 'D'}, + {"profile-list", no_argument, 0, 'H'}, + {"profile-set", required_argument, 0, 'c'}, + {"mon-interval", required_argument, 0, 'i'}, + {"mon-pid", required_argument, 0, 'p'}, + {"mon-core", required_argument, 0, 'm'}, + {"mon-time", required_argument, 0, 't'}, + {"mon-top", no_argument, 0, 'T'}, + {"mon-file", required_argument, 0, 'o'}, + {"mon-file-type", required_argument, 0, 'u'}, + {"mon-reset", no_argument, 0, 'r'}, + {"disable-mon-ipc", no_argument, 0, OPTION_DISABLE_MON_IPC}, + {"disable-mon-llc_miss", no_argument, 0, + OPTION_DISABLE_MON_LLC_MISS}, + {"alloc-class", required_argument, 0, 'e'}, + {"alloc-reset", required_argument, 0, 'R'}, + {"alloc-assoc", required_argument, 0, 'a'}, + {"verbose", no_argument, 0, 'v'}, + {"super-verbose", no_argument, 0, 'V'}, + {"iface-os", no_argument, 0, 'I'}, + {"percent-llc", no_argument, 0, 'P'}, + {"version", no_argument, 0, 'w'}, #ifdef PQOS_RMID_CUSTOM - {"rmid", required_argument, 0, OPTION_RMID}, + {"rmid", required_argument, 0, OPTION_RMID}, #endif {0, 0, 0, 0} /* end */ }; @@ -840,6 +850,8 @@ parse_config_file(sel_config_file); break; case 'i': + if (optarg == NULL) + return EXIT_FAILURE; selfn_monitor_interval(optarg); break; case 'p': @@ -950,6 +962,12 @@ case 'I': selfn_iface_os(NULL); break; + case OPTION_DISABLE_MON_IPC: + selfn_monitor_disable_ipc(NULL); + break; + case OPTION_DISABLE_MON_LLC_MISS: + selfn_monitor_disable_llc_miss(NULL); + break; #ifdef PQOS_RMID_CUSTOM case OPTION_RMID: selfn_monitor_rmids(optarg); @@ -1151,7 +1169,7 @@ /** * Close file descriptor for message log */ - if (cfg.fd_log > 0 && cfg.fd_log != STDOUT_FILENO) + if (sel_log_file != NULL && cfg.fd_log != -1) close(cfg.fd_log); /** diff -Nru intel-cmt-cat-3.2/pqos/main.h intel-cmt-cat-4.0/pqos/main.h --- intel-cmt-cat-3.2/pqos/main.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/main.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/Makefile intel-cmt-cat-4.0/pqos/Makefile --- intel-cmt-cat-3.2/pqos/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2014-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -136,14 +136,28 @@ -rm -f $(APP) $(OBJS) $(DEPFILES) ./*~ CHECKPATCH?=checkpatch.pl -.PHONY: style -style: +.PHONY: checkpatch +checkpatch: $(CHECKPATCH) --no-tree --no-signoff --emacs \ --ignore CODE_INDENT,INITIALISED_STATIC,LEADING_SPACE,SPLIT_STRING,UNSPECIFIED_INT,ARRAY_SIZE,\ SPDX_LICENSE_TAG,CONST_STRUCT \ -f main.c -f main.h -f monitor.c -f monitor.h -f alloc.c -f alloc.h -f profiles.c -f profiles.h \ -f cap.h -f cap.c -f common.h -f common.c +CLANGFORMAT?=clang-format +.PHONY: clang-format +clang-format: + @for file in "cap.c" "cap.h" "common.c"; do \ + echo "Checking style $$file"; \ + $(CLANGFORMAT) -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ + { echo "ERROR: $$file has style problems"; exit 1; } \ + done + +.PHONY: style +style: + $(MAKE) checkpatch + $(MAKE) clang-format + CPPCHECK?=cppcheck .PHONY: cppcheck cppcheck: diff -Nru intel-cmt-cat-3.2/pqos/monitor.c intel-cmt-cat-4.0/pqos/monitor.c --- intel-cmt-cat-3.2/pqos/monitor.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/monitor.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +56,7 @@ #include "monitor.h" #define PQOS_MAX_PID_MON_GROUPS 256 -#define PQOS_MON_EVENT_ALL -1 +#define PQOS_MON_EVENT_ALL ((enum pqos_mon_event)~PQOS_MON_EVENT_TMEM_BW) #define PID_COL_STATUS (3) /**< col for process status letter*/ #define PID_COL_UTIME (14) /**< col for cpu-user time in /proc/pid/stat*/ #define PID_COL_STIME (15) /**< col for cpu-kernel time in /proc/pid/stat*/ @@ -90,6 +90,11 @@ */ static int sel_monitor_num = 0; +/** Trigger for disabling ipc monitoring */ +static int sel_disable_ipc = 0; +/** Trigger for disabling llc_miss monitoring */ +static int sel_disable_llc_miss = 0; + /** * The mask to tell which events to display */ @@ -564,16 +569,15 @@ * Set event value and sel_event_max which determines * what events to display (out of all possible) */ - if (strncasecmp(str, "llc:", 4) == 0) { + if (strncasecmp(str, "llc:", 4) == 0) *evt = PQOS_MON_EVENT_L3_OCCUP; - sel_events_max |= *evt; - } else if (strncasecmp(str, "mbr:", 4) == 0) { + else if (strncasecmp(str, "mbr:", 4) == 0) *evt = PQOS_MON_EVENT_RMEM_BW; - sel_events_max |= *evt; - } else if (strncasecmp(str, "mbl:", 4) == 0) { + else if (strncasecmp(str, "mbl:", 4) == 0) *evt = PQOS_MON_EVENT_LMEM_BW; - sel_events_max |= *evt; - } else if (strncasecmp(str, "all:", 4) == 0 || + else if (strncasecmp(str, "mbt:", 4) == 0) + *evt = PQOS_MON_EVENT_TMEM_BW; + else if (strncasecmp(str, "all:", 4) == 0 || strncasecmp(str, ":", 1) == 0) *evt = (enum pqos_mon_event) PQOS_MON_EVENT_ALL; else @@ -670,6 +674,18 @@ sel_llc_format = LLC_FORMAT_PERCENT; } +void selfn_monitor_disable_ipc(const char *arg) +{ + UNUSED_ARG(arg); + sel_disable_ipc = 1; +} + +void selfn_monitor_disable_llc_miss(const char *arg) +{ + UNUSED_ARG(arg); + sel_disable_llc_miss = 1; +} + void selfn_monitor_cores(const char *arg) { char *cp = NULL, *str = NULL; @@ -695,14 +711,55 @@ free(cp); } +/** + * Update list of events to be monitored + * + * @param [inout] events List of monitoring events + * @param [in] cap_mon monitoring capability + */ +static void monitor_setup_events(enum pqos_mon_event *events, + const struct pqos_capability * const cap_mon) +{ + unsigned i; + enum pqos_mon_event all_evts = (enum pqos_mon_event)0; + + /** + * get all available events on this platform + */ + for (i = 0; i < cap_mon->u.mon->num_events; i++) { + struct pqos_monitor *mon = &cap_mon->u.mon->events[i]; + + all_evts |= mon->type; + } + + /* Disable IPC monitoring */ + if (sel_disable_ipc) + all_evts &= (enum pqos_mon_event)(~PQOS_PERF_EVENT_IPC); + /* Disable LLC miss monitoring */ + if (sel_disable_llc_miss) + all_evts &= (enum pqos_mon_event)(~PQOS_PERF_EVENT_LLC_MISS); + + /* check if all available events were selected */ + if ((*events & PQOS_MON_EVENT_ALL) == PQOS_MON_EVENT_ALL) { + *events = (enum pqos_mon_event)(all_evts & *events); + + /* Start IPC and LLC miss monitoring if available */ + } else { + if (all_evts & PQOS_PERF_EVENT_IPC) + *events |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC; + if (all_evts & PQOS_PERF_EVENT_LLC_MISS) + *events |= (enum pqos_mon_event) + PQOS_PERF_EVENT_LLC_MISS; + } + + sel_events_max |= *events; +} + int monitor_setup(const struct pqos_cpuinfo *cpu_info, const struct pqos_capability * const cap_mon) { unsigned i; int ret; - enum pqos_mon_event all_evts = (enum pqos_mon_event)0; - const enum pqos_mon_event evt_all = - (enum pqos_mon_event)PQOS_MON_EVENT_ALL; ASSERT(sel_monitor_num >= 0); ASSERT(sel_process_num >= 0); @@ -734,9 +791,9 @@ } else { if (strcasecmp(sel_output_type, "xml") == 0 || strcasecmp(sel_output_type, "csv") == 0) - fp_monitor = fopen_check_symlink(sel_output_file, "w+"); + fp_monitor = pqos_fopen(sel_output_file, "w+"); else - fp_monitor = fopen_check_symlink(sel_output_file, "a"); + fp_monitor = pqos_fopen(sel_output_file, "a"); if (fp_monitor == NULL) { perror("Monitoring output file open error:"); printf("Error opening '%s' output file!\n", @@ -750,19 +807,10 @@ } /** - * get all available events on this platform - */ - for (i = 0; i < cap_mon->u.mon->num_events; i++) { - struct pqos_monitor *mon = &cap_mon->u.mon->events[i]; - - all_evts |= mon->type; - } - /** * If no cores and events selected through command line * by default let's monitor all cores */ if (sel_monitor_num == 0 && sel_process_num == 0) { - sel_events_max = all_evts; for (i = 0; i < cpu_info->num_cores; i++) { unsigned lcore = cpu_info->cores[i].lcore; uint64_t core = (uint64_t)lcore; @@ -777,7 +825,7 @@ printf("Core group setup error!\n"); exit(EXIT_FAILURE); } - pg->events = sel_events_max; + pg->events = (enum pqos_mon_event) PQOS_MON_EVENT_ALL; pg->pgrp = malloc(sizeof(*pg->pgrp)); if (pg->pgrp == NULL) { printf("Error with memory allocation!\n"); @@ -798,18 +846,7 @@ for (i = 0; i < (unsigned)sel_monitor_num; i++) { struct core_group *cg = &sel_monitor_core_tab[i]; - /* check if all available events were selected */ - if (cg->events == evt_all) { - cg->events = all_evts; - sel_events_max |= all_evts; - } else { - if (all_evts & PQOS_PERF_EVENT_IPC) - cg->events |= (enum pqos_mon_event) - PQOS_PERF_EVENT_IPC; - if (all_evts & PQOS_PERF_EVENT_LLC_MISS) - cg->events |= (enum pqos_mon_event) - PQOS_PERF_EVENT_LLC_MISS; - } + monitor_setup_events(&cg->events, cap_mon); ret = pqos_mon_start(cg->num_cores, cg->cores, cg->events, (void *)cg->desc, @@ -846,18 +883,8 @@ for (i = 0; i < (unsigned)sel_process_num; i++) { struct pid_group *pg = &sel_monitor_pid_tab[i]; - /* check if all available events were selected */ - if (pg->events == evt_all) { - pg->events = all_evts; - sel_events_max |= all_evts; - } else { - if (all_evts & PQOS_PERF_EVENT_IPC) - pg->events |= (enum pqos_mon_event) - PQOS_PERF_EVENT_IPC; - if (all_evts & PQOS_PERF_EVENT_LLC_MISS) - pg->events |= (enum pqos_mon_event) - PQOS_PERF_EVENT_LLC_MISS; - } + monitor_setup_events(&pg->events, cap_mon); + ret = pqos_mon_start_pids(pg->num_pids, pg->pids, pg->events, (void *)pg->desc, pg->pgrp); @@ -1169,6 +1196,7 @@ return -1; } else { strncpy(val, token, len_val); + val[len_val - 1] = '\0'; return 0;/*value can be read from *val param*/ } } @@ -1369,10 +1397,10 @@ cores_s_len = strlen(cores_s); if (i != 0 && (cores_s_len + str_len + comma_len) < len) { - strcat(cores_s, ","); - strcat(cores_s, core); + strncat(cores_s, ",", len - cores_s_len); + strncat(cores_s, core, len - cores_s_len - comma_len); } else if (i == 0 && (cores_s_len + str_len) < len) - strcat(cores_s, core); + strncat(cores_s, core, len - cores_s_len); else { result = -1; goto free_memory; @@ -1958,8 +1986,12 @@ * @return Number of characters added to \a data excluding NULL */ static size_t -fillin_text_column(const double val, char data[], const size_t sz_data, - const int is_monitored, const int is_column_present) +fillin_text_column(const char *format, + const double val, + char data[], + const size_t sz_data, + const int is_monitored, + const int is_column_present) { static const char blank_column[] = " "; size_t offset = 0; @@ -1971,7 +2003,7 @@ /** * This is monitored and we have the data */ - snprintf(data, sz_data - 1, " %11.1f", val); + snprintf(data, sz_data - 1, format, val); offset = strlen(data); } else if (is_column_present) { /** @@ -1987,6 +2019,7 @@ /** * @brief Fills in single XML column in the monitoring table * + * @param format numerical value format * @param val numerical value to be put into the column * @param data place to put formatted column into * @param sz_data available size for the column @@ -1997,18 +2030,26 @@ * @return Number of characters added to \a data excluding NULL */ static size_t -fillin_xml_column(const double val, char data[], const size_t sz_data, - const int is_monitored, const int is_column_present, +fillin_xml_column(const char *const format, + const double val, + char data[], + const size_t sz_data, + const int is_monitored, + const int is_column_present, const char node_name[]) { size_t offset = 0; if (is_monitored) { + char formatted_val[16]; + + snprintf(formatted_val, 15, format, val); + /** * This is monitored and we have the data */ - snprintf(data, sz_data - 1, "\t<%s>%.1f\n", - node_name, val, node_name); + snprintf(data, sz_data - 1, "\t<%s>%s\n", + node_name, formatted_val, node_name); offset = strlen(data); } else if (is_column_present) { /** @@ -2025,6 +2066,7 @@ /** * @brief Fills in single CSV column in the monitoring table * + * @param format numerical value format * @param val numerical value to be put into the column * @param data place to put formatted column into * @param sz_data available size for the column @@ -2034,8 +2076,12 @@ * @return Number of characters added to \a data excluding NULL */ static size_t -fillin_csv_column(const double val, char data[], const size_t sz_data, - const int is_monitored, const int is_column_present) +fillin_csv_column(const char *format, + const double val, + char data[], + const size_t sz_data, + const int is_monitored, + const int is_column_present) { size_t offset = 0; @@ -2043,7 +2089,7 @@ /** * This is monitored and we have the data */ - snprintf(data, sz_data - 1, ",%.1f", val); + snprintf(data, sz_data - 1, format, val); offset = strlen(data); } else if (is_column_present) { /** @@ -2064,15 +2110,17 @@ * @param llc_entry LLC occupancy data structure * @param mbr remote memory bandwidth data * @param mbl local memory bandwidth data + * @param mbt total memory bandwidth data */ static void print_text_row(FILE *fp, struct pqos_mon_data *mon_data, const struct llc_entry_data *llc_entry, const double mbr, - const double mbl) + const double mbl, + const double mbt) { - const size_t sz_data = 128; + const size_t sz_data = 256; char data[sz_data]; size_t offset = 0; char core_list[PQOS_MAX_CORES * 4]; @@ -2083,25 +2131,55 @@ memset(data, 0, sz_data); - offset += fillin_text_column(llc_entry->val, data + offset, +#ifdef PQOS_RMID_CUSTOM + if (sel_interface == PQOS_INTER_MSR) { + pqos_rmid_t rmid; + int ret = pqos_mon_assoc_get(mon_data->cores[0], &rmid); + + offset += + fillin_text_column(" %4.0f", + (double)rmid, + data + offset, + sz_data - offset, + ret == PQOS_RETVAL_OK, + sel_interface == PQOS_INTER_MSR); + } +#endif + + offset += fillin_text_column(" %11.2f", mon_data->values.ipc, + data + offset, + sz_data - offset, + mon_data->event & PQOS_PERF_EVENT_IPC, + sel_events_max & PQOS_PERF_EVENT_IPC); + + offset += fillin_text_column(" %10.0fk", (double) + mon_data->values.llc_misses_delta/1000, + data + offset, + sz_data - offset, + mon_data->event & PQOS_PERF_EVENT_LLC_MISS, + sel_events_max & PQOS_PERF_EVENT_LLC_MISS); + + offset += fillin_text_column(" %11.1f", llc_entry->val, data + offset, sz_data - offset, mon_data->event & PQOS_MON_EVENT_L3_OCCUP, sel_events_max & PQOS_MON_EVENT_L3_OCCUP); - offset += fillin_text_column(mbl, data + offset, sz_data - offset, + offset += fillin_text_column(" %11.1f", mbl, data + offset, + sz_data - offset, mon_data->event & PQOS_MON_EVENT_LMEM_BW, sel_events_max & PQOS_MON_EVENT_LMEM_BW); - fillin_text_column(mbr, data + offset, sz_data - offset, - mon_data->event & PQOS_MON_EVENT_RMEM_BW, - sel_events_max & PQOS_MON_EVENT_RMEM_BW); + offset += fillin_text_column(" %11.1f", mbr, data + offset, + sz_data - offset, + mon_data->event & PQOS_MON_EVENT_RMEM_BW, + sel_events_max & PQOS_MON_EVENT_RMEM_BW); + + fillin_text_column(" %11.1f", mbt, data + offset, sz_data - offset, + mon_data->event & PQOS_MON_EVENT_TMEM_BW, + sel_events_max & PQOS_MON_EVENT_TMEM_BW); if (!process_mode()) - fprintf(fp, "\n%8.8s %5.2f %7uk%s", - (char *)mon_data->context, - mon_data->values.ipc, - (unsigned)mon_data->values.llc_misses_delta/1000, - data); + fprintf(fp, "\n%8.8s%s", (char *)mon_data->context, data); else { memset(core_list, 0, sizeof(core_list)); @@ -2111,11 +2189,8 @@ strncat(core_list, "err", sizeof(core_list) - 1); } - fprintf(fp, "\n%8.8s %8.8s %6.2f %7uk%s", - (char *)mon_data->context, core_list, - mon_data->values.ipc, - (unsigned)mon_data->values.llc_misses_delta/1000, - data); + fprintf(fp, "\n%8.8s %8.8s%s", (char *)mon_data->context, + core_list, data); } } @@ -2128,57 +2203,99 @@ * @param llc_entry LLC occupancy data structure * @param mbr remote memory bandwidth data * @param mbl local memory bandwidth data + * @param mbt total memory bandwidth data */ static void -print_xml_row(FILE *fp, char *time, +print_xml_row(FILE *fp, + char *time, struct pqos_mon_data *mon_data, const struct llc_entry_data *llc_entry, const double mbr, - const double mbl) + const double mbl, + const double mbt) { - const size_t sz_data = 128; + const size_t sz_data = 256; char data[sz_data]; char core_list[PQOS_MAX_CORES * 4]; size_t offset = 0; + const char *l3_text = NULL; ASSERT(fp != NULL); ASSERT(time != NULL); ASSERT(mon_data != NULL); ASSERT(llc_entry != NULL); - const char *l3_text = (llc_entry->format == LLC_FORMAT_KILOBYTES) ? - "l3_occupancy_kB" : "l3_occupancy_percent"; + switch (llc_entry->format) { + case LLC_FORMAT_KILOBYTES: + l3_text = "l3_occupancy_kB"; + break; + case LLC_FORMAT_PERCENT: + l3_text = "l3_occupancy_percent"; + break; + } + +#ifdef PQOS_RMID_CUSTOM + if (sel_interface == PQOS_INTER_MSR) { + pqos_rmid_t rmid; + int ret = pqos_mon_assoc_get(mon_data->cores[0], &rmid); + + offset += fillin_xml_column("%.0f", + rmid, + data + offset, + sz_data - offset, + ret == PQOS_RETVAL_OK, + sel_interface == PQOS_INTER_MSR, + "rmid"); + } +#endif + + offset += fillin_xml_column("%.2f", mon_data->values.ipc, data + offset, + sz_data - offset, + mon_data->event & PQOS_PERF_EVENT_IPC, + sel_events_max & PQOS_PERF_EVENT_IPC, + "ipc"); + + offset += fillin_xml_column("%.0f", (double) + mon_data->values.llc_misses_delta, + data + offset, + sz_data - offset, + mon_data->event & PQOS_PERF_EVENT_LLC_MISS, + sel_events_max & PQOS_PERF_EVENT_LLC_MISS, + "llc_misses"); - offset += fillin_xml_column(llc_entry->val, data + offset, + offset += fillin_xml_column("%.1f", llc_entry->val, data + offset, sz_data - offset, mon_data->event & PQOS_MON_EVENT_L3_OCCUP, sel_events_max & PQOS_MON_EVENT_L3_OCCUP, l3_text); - offset += fillin_xml_column(mbl, data + offset, sz_data - offset, + offset += fillin_xml_column("%.1f", mbl, data + offset, + sz_data - offset, mon_data->event & PQOS_MON_EVENT_LMEM_BW, sel_events_max & PQOS_MON_EVENT_LMEM_BW, "mbm_local_MB"); - fillin_xml_column(mbr, data + offset, sz_data - offset, - mon_data->event & PQOS_MON_EVENT_RMEM_BW, - sel_events_max & PQOS_MON_EVENT_RMEM_BW, - "mbm_remote_MB"); + offset += fillin_xml_column("%.1f", mbr, data + offset, + sz_data - offset, + mon_data->event & PQOS_MON_EVENT_RMEM_BW, + sel_events_max & PQOS_MON_EVENT_RMEM_BW, + "mbm_remote_MB"); + + fillin_xml_column("%.1f", mbt, data + offset, sz_data - offset, + mon_data->event & PQOS_MON_EVENT_TMEM_BW, + sel_events_max & PQOS_MON_EVENT_TMEM_BW, + "mbm_total_MB"); if (!process_mode()) fprintf(fp, "%s\n" "\t\n" "\t%s\n" - "\t%.2f\n" - "\t%llu\n" "%s" "%s\n", xml_child_open, time, (char *)mon_data->context, - mon_data->values.ipc, - (unsigned long long)mon_data->values.llc_misses_delta, data, xml_child_close); else { @@ -2195,16 +2312,12 @@ "\t\n" "\t%s\n" "\t%s\n" - "\t%.2f\n" - "\t%llu\n" "%s" "%s\n", xml_child_open, time, (char *)mon_data->context, core_list, - mon_data->values.ipc, - (unsigned long long)mon_data->values.llc_misses_delta, data, xml_child_close); } @@ -2219,13 +2332,15 @@ * @param llc_entry LLC occupancy data structure * @param mbr remote memory bandwidth data * @param mbl local memory bandwidth data + * @param mbt total memory bandwidth data */ static void print_csv_row(FILE *fp, char *time, struct pqos_mon_data *mon_data, const struct llc_entry_data *llc_entry, const double mbr, - const double mbl) + const double mbl, + const double mbt) { const size_t sz_data = 128; char data[sz_data]; @@ -2239,26 +2354,56 @@ memset(data, 0, sz_data); - offset += fillin_csv_column(llc_entry->val, data + offset, +#ifdef PQOS_RMID_CUSTOM + if (sel_interface == PQOS_INTER_MSR) { + pqos_rmid_t rmid; + int ret = pqos_mon_assoc_get(mon_data->cores[0], &rmid); + + offset += fillin_csv_column(",%.0f", + rmid, + data + offset, + sz_data - offset, + ret == PQOS_RETVAL_OK, + sel_interface == PQOS_INTER_MSR); + } +#endif + + offset += fillin_csv_column(",%.2f", mon_data->values.ipc, + data + offset, + sz_data - offset, + mon_data->event & PQOS_PERF_EVENT_IPC, + sel_events_max & PQOS_PERF_EVENT_IPC); + + offset += fillin_csv_column(",%.0f", (double) + mon_data->values.llc_misses_delta, + data + offset, + sz_data - offset, + mon_data->event & PQOS_PERF_EVENT_LLC_MISS, + sel_events_max & PQOS_PERF_EVENT_LLC_MISS); + + offset += fillin_csv_column(",%.1f", llc_entry->val, data + offset, sz_data - offset, mon_data->event & PQOS_MON_EVENT_L3_OCCUP, sel_events_max & PQOS_MON_EVENT_L3_OCCUP); - offset += fillin_csv_column(mbl, data + offset, sz_data - offset, + offset += fillin_csv_column(",%.1f", mbl, data + offset, + sz_data - offset, mon_data->event & PQOS_MON_EVENT_LMEM_BW, sel_events_max & PQOS_MON_EVENT_LMEM_BW); - fillin_csv_column(mbr, data + offset, sz_data - offset, - mon_data->event & PQOS_MON_EVENT_RMEM_BW, - sel_events_max & PQOS_MON_EVENT_RMEM_BW); + offset += fillin_csv_column(",%.1f", mbr, data + offset, + sz_data - offset, + mon_data->event & PQOS_MON_EVENT_RMEM_BW, + sel_events_max & PQOS_MON_EVENT_RMEM_BW); + + fillin_csv_column(",%.1f", mbt, data + offset, sz_data - offset, + mon_data->event & PQOS_MON_EVENT_TMEM_BW, + sel_events_max & PQOS_MON_EVENT_TMEM_BW); if (!process_mode()) fprintf(fp, - "%s,\"%s\",%.2f,%llu%s\n", - time, (char *)mon_data->context, - mon_data->values.ipc, - (unsigned long long)mon_data->values.llc_misses_delta, - data); + "%s,\"%s\"%s\n", + time, (char *)mon_data->context, data); else { memset(core_list, 0, sizeof(core_list)); @@ -2269,11 +2414,8 @@ } fprintf(fp, - "%s,\"%s\",%s,%.2f,%llu%s\n", - time, (char *)mon_data->context, core_list, - mon_data->values.ipc, - (unsigned long long)mon_data->values.llc_misses_delta, - data); + "%s,\"%s\",%s%s\n", + time, (char *)mon_data->context, core_list, data); } } @@ -2301,11 +2443,20 @@ return; if (istext) { - if (!process_mode()) - strncpy(hdr, " CORE IPC MISSES", sz_hdr - 1); - else - strncpy(hdr, " PID CORE IPC MISSES", - sz_hdr - 1); + if (!process_mode()) { + strncpy(hdr, " CORE", sz_hdr - 1); +#ifdef PQOS_RMID_CUSTOM + if (sel_interface == PQOS_INTER_MSR) + strncat(hdr, " RMID", + sz_hdr - strlen(hdr) - 1); +#endif + } else + strncpy(hdr, " PID CORE", sz_hdr - 1); + + if (sel_events_max & PQOS_PERF_EVENT_IPC) + strncat(hdr, " IPC", sz_hdr - strlen(hdr) - 1); + if (sel_events_max & PQOS_PERF_EVENT_LLC_MISS) + strncat(hdr, " MISSES", sz_hdr - strlen(hdr) - 1); if (sel_events_max & PQOS_MON_EVENT_L3_OCCUP) { if (format == LLC_FORMAT_KILOBYTES) strncat(hdr, " LLC[KB]", @@ -2318,15 +2469,24 @@ strncat(hdr, " MBL[MB/s]", sz_hdr - strlen(hdr) - 1); if (sel_events_max & PQOS_MON_EVENT_RMEM_BW) strncat(hdr, " MBR[MB/s]", sz_hdr - strlen(hdr) - 1); + if (sel_events_max & PQOS_MON_EVENT_TMEM_BW) + strncat(hdr, " MBT[MB/s]", sz_hdr - strlen(hdr) - 1); } if (iscsv) { - if (!process_mode()) - strncpy(hdr, "Time,Core,IPC,LLC Misses", - sz_hdr - 1); - else - strncpy(hdr, "Time,PID,Core,IPC,LLC Misses", - sz_hdr - 1); + if (!process_mode()) { + strncpy(hdr, "Time,Core", sz_hdr - 1); +#ifdef PQOS_RMID_CUSTOM + if (sel_interface == PQOS_INTER_MSR) + strncat(hdr, ",RMID", sz_hdr - strlen(hdr) - 1); +#endif + } else + strncpy(hdr, "Time,PID,Core", sz_hdr - 1); + + if (sel_events_max & PQOS_PERF_EVENT_IPC) + strncat(hdr, ",IPC", sz_hdr - strlen(hdr) - 1); + if (sel_events_max & PQOS_PERF_EVENT_LLC_MISS) + strncat(hdr, ",LLC Misses", sz_hdr - strlen(hdr) - 1); if (sel_events_max & PQOS_MON_EVENT_L3_OCCUP) { if (format == LLC_FORMAT_KILOBYTES) strncat(hdr, ",LLC[KB]", @@ -2339,6 +2499,8 @@ strncat(hdr, ",MBL[MB/s]", sz_hdr - strlen(hdr) - 1); if (sel_events_max & PQOS_MON_EVENT_RMEM_BW) strncat(hdr, ",MBR[MB/s]", sz_hdr - strlen(hdr) - 1); + if (sel_events_max & PQOS_MON_EVENT_TMEM_BW) + strncat(hdr, ",MBT[MB/s]", sz_hdr - strlen(hdr) - 1); } } @@ -2616,16 +2778,17 @@ double mbr = bytes_to_mb(pv->mbm_remote_delta) * coeff; double mbl = bytes_to_mb(pv->mbm_local_delta) * coeff; + double mbt = bytes_to_mb(pv->mbm_total_delta) * coeff; if (istext) print_text_row(fp_monitor, mon_data[i], - &llc_entry, mbr, mbl); + &llc_entry, mbr, mbl, mbt); if (isxml) print_xml_row(fp_monitor, cb_time, mon_data[i], - &llc_entry, mbr, mbl); + &llc_entry, mbr, mbl, mbt); if (iscsv) print_csv_row(fp_monitor, cb_time, mon_data[i], - &llc_entry, mbr, mbl); + &llc_entry, mbr, mbl, mbt); } if (!istty && istext) fputs("\n", fp_monitor); diff -Nru intel-cmt-cat-3.2/pqos/monitor.h intel-cmt-cat-4.0/pqos/monitor.h --- intel-cmt-cat-3.2/pqos/monitor.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/monitor.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,6 +111,16 @@ */ void selfn_monitor_set_llc_percent(void); +/* + * @brief Allows to disable IPC monitoring + */ +void selfn_monitor_disable_ipc(const char *arg); + +/* + * @brief Allows to disable LLC misses monitoring + */ +void selfn_monitor_disable_llc_miss(const char *arg); + /** * @brief Stops monitoring on selected core(s)/pid(s) * diff -Nru intel-cmt-cat-3.2/pqos/pqos.8 intel-cmt-cat-4.0/pqos/pqos.8 --- intel-cmt-cat-3.2/pqos/pqos.8 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/pqos.8 2020-06-19 10:42:55.000000000 +0000 @@ -2,7 +2,7 @@ .\" 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 PQOS 8 "January 04, 2019" +.TH PQOS 8 "May 08, 2020" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -16,16 +16,16 @@ .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME -pqos, pqos-msr, pqos-os \- Intel(R) Resource Director Technology monitoring and control tool +pqos, pqos-msr, pqos-os \- Intel(R) Resource Director Technology/AMD PQoS monitoring and control tool .br .SH SYNOPSIS .B pqos .RI [ OPTIONS ]... .SH DESCRIPTION -Intel(R) Resource Director Technology is designed to monitor and manage cpu -resources and improve performance of applications and virtual machines. +Intel(R) Resource Director Technology/AMD PQoS is designed to monitor and manage +cpu resources and improve performance of applications and virtual machines. .PP -Intel(R) Resource Director Technology includes monitoring and control +Intel(R) Resource Director Technology/AMD PQoS includes monitoring and control technologies. Monitoring technologies include CMT (Cache Monitoring Technology), which monitors occupancy of last level cache, and MBM (Memory Bandwidth Monitoring). Control technologies include CAT (Cache Allocation Technology), CDP (Code Data @@ -60,10 +60,10 @@ show the current allocation and monitoring configuration .TP .B -d, \-\-display -display supported Intel(R) Resource Director Technology capabilities +display supported Intel(R) Resource Director Technology/AMD PQoS capabilities .TP .B -D, \-\-display\-verbose -display supported Intel(R) Resource Director Technology capabilities in verbose mode +display supported Intel(R) Resource Director Technology/AMD PQoS capabilities in verbose mode .TP .B \-f FILE, \-\-config\-file=FILE load commands from selected configuration FILE @@ -172,7 +172,9 @@ .br \- "mbl" for MBL (local memory bandwidth) .br -\- "all" or "" for all detected event types +\- "mbt" for MBT (total memory bandwidth) +.br +\- "all" or "" for all detected event types (except MBT) .br CORE_LIST is comma or dash separated list of cores. .br @@ -233,6 +235,12 @@ .B \-r, \-\-mon\-reset reset monitoring and use all RMID's and cores in the system .TP +.B \-\-disable-mon-ipc +Disable IPC monitoring +.TP +.B \-\-disable-mon-llc_miss +Disable LLC misses monitoring +.TP .B \-H, \-\-profile\-list list supported allocation profiles .TP diff -Nru intel-cmt-cat-3.2/pqos/pqos-msr intel-cmt-cat-4.0/pqos/pqos-msr --- intel-cmt-cat-3.2/pqos/pqos-msr 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/pqos-msr 2020-06-19 10:42:55.000000000 +0000 @@ -3,7 +3,7 @@ ############################################################################### # BSD LICENSE # -# Copyright(c) 2017-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2017-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/pqos-os intel-cmt-cat-4.0/pqos/pqos-os --- intel-cmt-cat-3.2/pqos/pqos-os 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/pqos-os 2020-06-19 10:42:55.000000000 +0000 @@ -3,7 +3,7 @@ ############################################################################### # BSD LICENSE # -# Copyright(c) 2017-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2017-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/pqos/profiles.c intel-cmt-cat-4.0/pqos/profiles.c --- intel-cmt-cat-3.2/pqos/profiles.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/profiles.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -377,7 +377,7 @@ unsigned i = 0, offset = 0; memset(cb, 0, sizeof(cb)); - strcpy(cb, "llc:"); + strncpy(cb, "llc:", sizeof(cb)); offset = (unsigned)strlen("llc:"); for (i = 0; i < cnum; i++) { diff -Nru intel-cmt-cat-3.2/pqos/profiles.h intel-cmt-cat-4.0/pqos/profiles.h --- intel-cmt-cat-3.2/pqos/profiles.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/pqos/profiles.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2014-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2014-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/rdtset/common.c intel-cmt-cat-4.0/rdtset/common.c --- intel-cmt-cat-3.2/rdtset/common.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/common.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@ #include "common.h" #include "rdt.h" +struct rdtset g_cfg; + int str_to_cpuset(const char *cpustr, const unsigned cpustr_len, cpu_set_t *cpuset) { diff -Nru intel-cmt-cat-3.2/rdtset/common.h intel-cmt-cat-4.0/rdtset/common.h --- intel-cmt-cat-3.2/rdtset/common.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/common.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ extern "C" { #endif -#define RDT_MAX_PIDS 128 +#define RDT_MAX_PIDS 128 #define MAX_OPTARG_LEN 64 /** @@ -52,6 +52,11 @@ */ #define RDT_MAX_MBA 100 +/** + * MBA max value for AMD. + */ +#define RDT_MAX_MBA_AMD 0x800 + #ifndef MIN /** * Macro to return the minimum of two numbers @@ -171,7 +176,7 @@ enum pqos_interface interface; /**< pqos interface to use */ }; -struct rdtset g_cfg; +extern struct rdtset g_cfg; #define DBG(...) \ do { \ diff -Nru intel-cmt-cat-3.2/rdtset/cpu.c intel-cmt-cat-4.0/rdtset/cpu.c --- intel-cmt-cat-3.2/rdtset/cpu.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/cpu.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/rdtset/cpu.h intel-cmt-cat-4.0/rdtset/cpu.h --- intel-cmt-cat-3.2/rdtset/cpu.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/cpu.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/rdtset/Makefile intel-cmt-cat-4.0/rdtset/Makefile --- intel-cmt-cat-3.2/rdtset/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -141,11 +141,12 @@ -f common.c -f common.h \ -f mba_sc.h -f mba_sc.c +CLANGFORMAT?=clang-format .PHONY: clang-format clang-format: @for file in $(wildcard *.[ch]); do \ echo "Checking style $$file"; \ - clang-format -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ + $(CLANGFORMAT) -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ { echo "ERROR: $$file has style problems"; exit 1; } \ done diff -Nru intel-cmt-cat-3.2/rdtset/mba_sc.c intel-cmt-cat-4.0/rdtset/mba_sc.c --- intel-cmt-cat-3.2/rdtset/mba_sc.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/mba_sc.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/rdtset/mba_sc.h intel-cmt-cat-4.0/rdtset/mba_sc.h --- intel-cmt-cat-3.2/rdtset/mba_sc.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/mba_sc.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +38,7 @@ #include "common.h" #define MBA_SC_SAMPLING_INTERVAL 100 /**< Sampling interval in ms */ -#define MBA_SC_DEF_INIT_MBA 100 /**< Default, initial MBA value, 100% */ +#define MBA_SC_DEF_INIT_MBA 100 /**< Default, initial MBA value, 100% */ /** * @brief Initializes SW controller module diff -Nru intel-cmt-cat-3.2/rdtset/rdt.c intel-cmt-cat-4.0/rdtset/rdt.c --- intel-cmt-cat-3.2/rdtset/rdt.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/rdt.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -159,10 +159,7 @@ (cfg.u.l3->cdp == 0 && cfg.u.l3->u.ways_mask != 0)); case PQOS_CAP_TYPE_MBA: - return cfg.u.mba != NULL && cfg.u.mba->mb_max > 0 && - ((cfg.u.mba->ctrl == 0 && - cfg.u.mba->mb_max <= RDT_MAX_MBA) || - cfg.u.mba->ctrl == 1); + return cfg.u.mba != NULL && cfg.u.mba->mb_max > 0; default: break; @@ -459,7 +456,7 @@ return -EINVAL; ret = str_to_uint64(param, 10, &rate); - if (ret < 0 || rate == 0 || rate > RDT_MAX_MBA) + if (ret < 0 || rate == 0) return -EINVAL; mba.u.mba->ctrl = 0; @@ -1296,6 +1293,9 @@ struct pqos_l3ca *l3_def, struct pqos_mba *mba_def) { + if (m_cpu == NULL) + return -EINVAL; + if (l2_def == NULL && l3_def == NULL && mba_def == NULL) return -EINVAL; @@ -1336,7 +1336,9 @@ mba_def->ctrl = 1; mba_def->mb_max = UINT32_MAX; } else - mba_def->mb_max = RDT_MAX_MBA; + mba_def->mb_max = (m_cpu->vendor == PQOS_VENDOR_AMD) + ? RDT_MAX_MBA_AMD + : RDT_MAX_MBA; } return 0; @@ -1369,6 +1371,9 @@ const struct pqos_coreinfo *ci = NULL; int ret; + if (m_cpu == NULL) + return -EINVAL; + if (NULL == l2ca && NULL == l3ca && NULL == mba) return -EINVAL; @@ -1439,7 +1444,9 @@ if (!rdt_cfg_is_valid(wrap_mba(&mba_requested))) mba_requested = mba_defs; else if (mba_sc_mode(&g_cfg)) { - mba_requested.mb_max = RDT_MAX_MBA; + mba_requested.mb_max = + (m_cpu->vendor == PQOS_VENDOR_AMD) ? RDT_MAX_MBA_AMD + : RDT_MAX_MBA; mba_requested.ctrl = 0; } @@ -1447,6 +1454,10 @@ mba_requested.class_id = cos_id; ret = pqos_mba_set(mba_id, 1, &mba_requested, &mba_actual); + if (ret == PQOS_RETVAL_PARAM) { + fprintf(stderr, "Invalid RDT parameters!\n"); + return -EINVAL; + } if (ret != PQOS_RETVAL_OK) { fprintf(stderr, "Error setting MBA COS#%u on mba id %u!\n", @@ -1492,28 +1503,26 @@ if (core_num == 0) return -EFAULT; - if (technology & (1 << PQOS_CAP_TYPE_L2CA)) { - const unsigned l2_technology = 1 << PQOS_CAP_TYPE_L2CA; - /* Assign all cores to single COS */ - ret = pqos_alloc_assign(l2_technology, core_array, core_num, - &cos_id); - switch (ret) { - case PQOS_RETVAL_OK: - break; - case PQOS_RETVAL_RESOURCE: - fprintf(stderr, "No free COS available!\n"); - return -EBUSY; - default: - fprintf(stderr, "Unable to assign COS!\n"); - return -EFAULT; - } + ret = get_max_res_id(technology, &max_id); + if (ret != 0) + return ret; - ret = get_max_res_id(l2_technology, &max_id); - if (ret != 0) - return ret; + /* Assign all cores to single group */ + ret = pqos_alloc_assign(technology, core_array, core_num, &cos_id); + switch (ret) { + case PQOS_RETVAL_OK: + break; + case PQOS_RETVAL_RESOURCE: + fprintf(stderr, "No free COS available!\n"); + return -EBUSY; + default: + fprintf(stderr, "Unable to assign COS L2!\n"); + return -EFAULT; + } - /* Set COS definition on necessary sockets/clusters */ - for (i = 0; i <= max_id; i++) { + /* Set COS definition on necessary sockets/clusters */ + for (i = 0; i <= max_id; i++) { + if (technology & (1 << PQOS_CAP_TYPE_L2CA)) { memset(core_array, 0, sizeof(core_array)); /* Get cores on res id i */ @@ -1530,30 +1539,7 @@ if (ret != 0) return ret; } - } - - if (technology & (1 << PQOS_CAP_TYPE_L3CA)) { - const unsigned l3_technology = 1 << PQOS_CAP_TYPE_L3CA; - /* Assign all cores to single COS */ - ret = pqos_alloc_assign(l3_technology, core_array, core_num, - &cos_id); - switch (ret) { - case PQOS_RETVAL_OK: - break; - case PQOS_RETVAL_RESOURCE: - fprintf(stderr, "No free COS available!\n"); - return -EBUSY; - default: - fprintf(stderr, "Unable to assign COS!\n"); - return -EFAULT; - } - - ret = get_max_res_id(l3_technology, &max_id); - if (ret != 0) - return ret; - - /* Set COS definition on necessary sockets/clusters */ - for (i = 0; i <= max_id; i++) { + if (technology & (1 << PQOS_CAP_TYPE_L3CA)) { memset(core_array, 0, sizeof(core_array)); /* Get cores on res id i */ @@ -1571,30 +1557,7 @@ if (ret != 0) return ret; } - } - - if (technology & (1 << PQOS_CAP_TYPE_MBA)) { - const unsigned mba_technology = 1 << PQOS_CAP_TYPE_MBA; - /* Assign all cores to single COS */ - ret = pqos_alloc_assign(mba_technology, core_array, core_num, - &cos_id); - switch (ret) { - case PQOS_RETVAL_OK: - break; - case PQOS_RETVAL_RESOURCE: - fprintf(stderr, "No free COS available!\n"); - return -EBUSY; - default: - fprintf(stderr, "Unable to assign COS!\n"); - return -EFAULT; - } - - ret = get_max_res_id(mba_technology, &max_id); - if (ret != 0) - return ret; - - /* Set COS definition on necessary sockets/clusters */ - for (i = 0; i <= max_id; i++) { + if (technology & (1 << PQOS_CAP_TYPE_MBA)) { memset(core_array, 0, sizeof(core_array)); /* Get cores on res id i */ @@ -1637,73 +1600,37 @@ const struct pqos_l3ca *l3ca, const struct pqos_mba *mba) { - int ret; - unsigned i, max_id; + int ret = PQOS_RETVAL_OK; + unsigned res_id, max_id; ret = get_max_res_id(technology, &max_id); if (ret != 0) return ret; /* Assign new COS for all applicable res ids */ - for (i = 0; i <= max_id; i++) { - const unsigned l2_technology = 1 << PQOS_CAP_TYPE_L2CA; + for (res_id = 0; res_id <= max_id; res_id++) { unsigned core_array[CPU_SETSIZE] = {0}; - unsigned core_num, cos_id; + unsigned core_num = 0, cos_id; + unsigned i; /* Get cores on res id i */ - if (technology & (1 << PQOS_CAP_TYPE_L2CA)) - ret = get_l2id_cores(cores, i, &core_num, core_array); - else - break; /* exit this loop */ - - if (ret != 0) - return ret; - - if (core_num == 0) - continue; - - /* Assign COS to those cores */ - ret = pqos_alloc_assign(l2_technology, core_array, core_num, - &cos_id); - switch (ret) { - case PQOS_RETVAL_OK: - break; - case PQOS_RETVAL_RESOURCE: - fprintf(stderr, "No free COS available!\n"); - return -EBUSY; - default: - fprintf(stderr, "Unable to assign COS!\n"); - return -EFAULT; + if (technology & (1 << PQOS_CAP_TYPE_L3CA)) { + ret = get_l3cat_id_cores(cores, res_id, &core_num, + core_array); + } else if (technology & (1 << PQOS_CAP_TYPE_MBA)) { + ret = get_mba_id_cores(cores, res_id, &core_num, + core_array); + } else if (technology & (1 << PQOS_CAP_TYPE_L2CA)) { + ret = get_l2id_cores(cores, res_id, &core_num, + core_array); } - - /* Configure COS on res ID i */ - ret = - cfg_configure_cos(l2ca, NULL, NULL, core_array[0], cos_id); if (ret != 0) return ret; - } - - /* Assign new COS for all applicable res ids */ - for (i = 0; i <= max_id; i++) { - const unsigned l3_technology = 1 << PQOS_CAP_TYPE_L3CA; - unsigned core_array[CPU_SETSIZE] = {0}; - unsigned core_num, cos_id; - - /* Get cores on res id i */ - if (technology & (1 << PQOS_CAP_TYPE_L3CA)) - ret = - get_l3cat_id_cores(cores, i, &core_num, core_array); - else - break; /* exit this loop */ - - if (ret != 0) - return ret; - if (core_num == 0) continue; /* Assign COS to those cores */ - ret = pqos_alloc_assign(l3_technology, core_array, core_num, + ret = pqos_alloc_assign(technology, core_array, core_num, &cos_id); switch (ret) { case PQOS_RETVAL_OK: @@ -1717,48 +1644,12 @@ } /* Configure COS on res ID i */ - ret = - cfg_configure_cos(NULL, l3ca, NULL, core_array[0], cos_id); - if (ret != 0) - return ret; - } - - /* Assign new COS for all applicable res ids */ - for (i = 0; i <= max_id; i++) { - const unsigned mba_technology = 1 << PQOS_CAP_TYPE_MBA; - unsigned core_array[CPU_SETSIZE] = {0}; - unsigned core_num, cos_id; - - /* Get cores on res id i */ - if (technology & (1 << PQOS_CAP_TYPE_MBA)) - ret = get_mba_id_cores(cores, i, &core_num, core_array); - else - break; /* exit this loop */ - - if (ret != 0) - return ret; - - if (core_num == 0) - continue; - - /* Assign COS to those cores */ - ret = pqos_alloc_assign(mba_technology, core_array, core_num, - &cos_id); - switch (ret) { - case PQOS_RETVAL_OK: - break; - case PQOS_RETVAL_RESOURCE: - fprintf(stderr, "No free COS available!\n"); - return -EBUSY; - default: - fprintf(stderr, "Unable to assign COS!\n"); - return -EFAULT; + for (i = 0; i < core_num; i++) { + ret = cfg_configure_cos(l2ca, l3ca, mba, core_array[i], + cos_id); + if (ret != 0) + return ret; } - - /* Configure COS on res ID i */ - ret = cfg_configure_cos(NULL, NULL, mba, core_array[0], cos_id); - if (ret != 0) - return ret; } return 0; diff -Nru intel-cmt-cat-3.2/rdtset/rdt.h intel-cmt-cat-4.0/rdtset/rdt.h --- intel-cmt-cat-3.2/rdtset/rdt.h 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/rdt.h 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/rdtset/rdtset.8 intel-cmt-cat-4.0/rdtset/rdtset.8 --- intel-cmt-cat-3.2/rdtset/rdtset.8 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/rdtset.8 2020-06-19 10:42:55.000000000 +0000 @@ -16,7 +16,7 @@ .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME -rtdset \- Task CPU affinity and Intel(R) Resource Director Technology control tool +rtdset \- Task CPU affinity and Intel(R) Resource Director Technology/AMD PQoS control tool .br .SH SYNOPSIS .B rdtset @@ -48,7 +48,7 @@ or closed-loop one monitoring local memory B/W usage and adjust MBA accordingly. For OS interface, it uses MBA CTRL via libpqos (OS support available in Linux kernel 4.18 or later). For MSRs, the tool adjusts MBA configuration by itself based on local memory B/W. -Intel(R) RDT allocation operations of the utility are done via libpqos library. Class of service 0 (CLOS0) +Intel(R) RDT/AMD PQoS allocation operations of the utility are done via libpqos library. Class of service 0 (CLOS0) is assumed as default one. In command mode, rdtset forks and one process executes the command. Another process waits for the task to terminate and restores default allocation state by assigning cpu's back to CLOS0. This behavior is not in place in PID mode. diff -Nru intel-cmt-cat-3.2/rdtset/rdtset.c intel-cmt-cat-4.0/rdtset/rdtset.c --- intel-cmt-cat-3.2/rdtset/rdtset.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rdtset/rdtset.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2016-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -420,16 +420,16 @@ static const struct option lgopts[] = { /* clang-format off */ - { "cpu", required_argument, 0, 'c' }, - { "pid", required_argument, 0, 'p' }, - { "reset", required_argument, 0, 'r' }, - { "rdt", required_argument, 0, 't' }, - { "sudokeep", no_argument, 0, 'k' }, - { "verbose", no_argument, 0, 'v' }, - { "iface-os", no_argument, 0, 'I' }, - { "help", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'w' }, - { NULL, 0, 0, 0 } + { "cpu", required_argument, 0, 'c' }, + { "pid", required_argument, 0, 'p' }, + { "reset", required_argument, 0, 'r' }, + { "rdt", required_argument, 0, 't' }, + { "sudokeep", no_argument, 0, 'k' }, + { "verbose", no_argument, 0, 'v' }, + { "iface-os", no_argument, 0, 'I' }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'w' }, + { NULL, 0, 0, 0 } /* clang-format on */ }; diff -Nru intel-cmt-cat-3.2/README intel-cmt-cat-4.0/README --- intel-cmt-cat-3.2/README 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/README 2020-06-19 10:42:55.000000000 +0000 @@ -260,6 +260,7 @@ Enable Intel(R) RDT support in: - kernel v4.10 - v4.13 with kernel configuration option CONFIG_INTEL_RDT_A - kernel v4.14+ with kernel configuration option CONFIG_INTEL_RDT +- kernel v5.0+ with kernel configuration option CONFIG_X86_RESCTRL Note: No kernel configuration options required before v4.10. diff -Nru intel-cmt-cat-3.2/rpm/intel-cmt-cat.spec intel-cmt-cat-4.0/rpm/intel-cmt-cat.spec --- intel-cmt-cat-3.2/rpm/intel-cmt-cat.spec 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/rpm/intel-cmt-cat.spec 2020-06-19 10:42:55.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright(c) 2016-2019, Intel Corporation +# Copyright(c) 2016-2020, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -24,7 +24,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. %global githubname intel-cmt-cat -%global githubver 3.2.0 +%global githubver 4.0.0 %if %{defined githubsubver} %global githubfull %{githubname}-%{githubver}.%{githubsubver} @@ -119,7 +119,7 @@ install -d %{buildroot}/%{_libdir} install -s %{_builddir}/%{githubfull}/lib/libpqos.so.* %{buildroot}/%{_libdir} cp -a %{_builddir}/%{githubfull}/lib/libpqos.so %{buildroot}/%{_libdir} -cp -a %{_builddir}/%{githubfull}/lib/libpqos.so.3 %{buildroot}/%{_libdir} +cp -a %{_builddir}/%{githubfull}/lib/libpqos.so.4 %{buildroot}/%{_libdir} # Install the header file install -d %{buildroot}/%{_includedir} @@ -173,6 +173,9 @@ %doc %{_usrsrc}/%{githubfull}/LICENSE %changelog +* Fri May 29 2020 Michal Aleksinski 4.0.0-1 +- New release 4.0.0 + * Wed Dec 4 2019 Michal Aleksinski 3.2.0-1 - New release 3.2.0 @@ -185,7 +188,7 @@ * Mon Jan 21 2019 Michal Aleksinski 3.0.0-1 - New release 3.0.0 -* Fri Oct 11 2018 Michal Aleksinski 2.1.0-1 +* Thu Oct 11 2018 Michal Aleksinski 2.1.0-1 - New release 2.1.0 * Mon Jun 18 2018 Michal Aleksinski 2.0.0-1 diff -Nru intel-cmt-cat-3.2/snmp/Makefile intel-cmt-cat-4.0/snmp/Makefile --- intel-cmt-cat-3.2/snmp/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/snmp/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -4,7 +4,7 @@ # @par # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/snmp/rdt-agentx.pl intel-cmt-cat-4.0/snmp/rdt-agentx.pl --- intel-cmt-cat-3.2/snmp/rdt-agentx.pl 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/snmp/rdt-agentx.pl 2020-06-19 10:42:55.000000000 +0000 @@ -3,7 +3,7 @@ # # BSD LICENSE # -# Copyright(c) 2016-2019 Intel Corporation. All rights reserved. +# Copyright(c) 2016-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/conftest.py intel-cmt-cat-4.0/tests/conftest.py --- intel-cmt-cat-3.2/tests/conftest.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/conftest.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/plugins/pytest_rdt.py intel-cmt-cat-4.0/tests/plugins/pytest_rdt.py --- intel-cmt-cat-3.2/tests/plugins/pytest_rdt.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/plugins/pytest_rdt.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/plugins/pytest_report.py intel-cmt-cat-4.0/tests/plugins/pytest_report.py --- intel-cmt-cat-3.2/tests/plugins/pytest_report.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/plugins/pytest_report.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/priority.py intel-cmt-cat-4.0/tests/priority.py --- intel-cmt-cat-3.2/tests/priority.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/priority.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/schema/env.json intel-cmt-cat-4.0/tests/schema/env.json --- intel-cmt-cat-3.2/tests/schema/env.json 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/schema/env.json 2020-06-19 10:42:55.000000000 +0000 @@ -87,6 +87,11 @@ "cos": { "description": "Number of classes", "$ref": "definitions.json#/uint_nonzero" + }, + "version": { + "description": "MBA version", + "type": "number", + "minimum": 0.0 } }, "required": ["cos"], diff -Nru intel-cmt-cat-3.2/tests/testcases/test_pqos_cmt.py intel-cmt-cat-4.0/tests/testcases/test_pqos_cmt.py --- intel-cmt-cat-3.2/tests/testcases/test_pqos_cmt.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_pqos_cmt.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_pqos_l2cat.py intel-cmt-cat-4.0/tests/testcases/test_pqos_l2cat.py --- intel-cmt-cat-3.2/tests/testcases/test_pqos_l2cat.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_pqos_l2cat.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_pqos_l3cat.py intel-cmt-cat-4.0/tests/testcases/test_pqos_l3cat.py --- intel-cmt-cat-3.2/tests/testcases/test_pqos_l3cat.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_pqos_l3cat.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_pqos_mba.py intel-cmt-cat-4.0/tests/testcases/test_pqos_mba.py --- intel-cmt-cat-3.2/tests/testcases/test_pqos_mba.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_pqos_mba.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_pqos_mbm.py intel-cmt-cat-4.0/tests/testcases/test_pqos_mbm.py --- intel-cmt-cat-3.2/tests/testcases/test_pqos_mbm.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_pqos_mbm.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test.py intel-cmt-cat-4.0/tests/testcases/test.py --- intel-cmt-cat-3.2/tests/testcases/test.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_rdtset_affinity.py intel-cmt-cat-4.0/tests/testcases/test_rdtset_affinity.py --- intel-cmt-cat-3.2/tests/testcases/test_rdtset_affinity.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_rdtset_affinity.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_rdtset_l2cat.py intel-cmt-cat-4.0/tests/testcases/test_rdtset_l2cat.py --- intel-cmt-cat-3.2/tests/testcases/test_rdtset_l2cat.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_rdtset_l2cat.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_rdtset_l3cat.py intel-cmt-cat-4.0/tests/testcases/test_rdtset_l3cat.py --- intel-cmt-cat-3.2/tests/testcases/test_rdtset_l3cat.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_rdtset_l3cat.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testcases/test_rdtset_mba.py intel-cmt-cat-4.0/tests/testcases/test_rdtset_mba.py --- intel-cmt-cat-3.2/tests/testcases/test_rdtset_mba.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testcases/test_rdtset_mba.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testlib/env.py intel-cmt-cat-4.0/tests/testlib/env.py --- intel-cmt-cat-3.2/tests/testlib/env.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testlib/env.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testlib/features_rdt_msr.py intel-cmt-cat-4.0/tests/testlib/features_rdt_msr.py --- intel-cmt-cat-3.2/tests/testlib/features_rdt_msr.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testlib/features_rdt_msr.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testlib/features_rdt_os.py intel-cmt-cat-4.0/tests/testlib/features_rdt_os.py --- intel-cmt-cat-3.2/tests/testlib/features_rdt_os.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testlib/features_rdt_os.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testlib/features_rdt.py intel-cmt-cat-4.0/tests/testlib/features_rdt.py --- intel-cmt-cat-3.2/tests/testlib/features_rdt.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testlib/features_rdt.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testlib/perf.py intel-cmt-cat-4.0/tests/testlib/perf.py --- intel-cmt-cat-3.2/tests/testlib/perf.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testlib/perf.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tests/testlib/resctrl.py intel-cmt-cat-4.0/tests/testlib/resctrl.py --- intel-cmt-cat-3.2/tests/testlib/resctrl.py 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tests/testlib/resctrl.py 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ ################################################################################ # BSD LICENSE # -# Copyright(c) 2019 Intel Corporation. All rights reserved. +# Copyright(c) 2019-2020 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff -Nru intel-cmt-cat-3.2/tools/membw/Makefile intel-cmt-cat-4.0/tools/membw/Makefile --- intel-cmt-cat-3.2/tools/membw/Makefile 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tools/membw/Makefile 2020-06-19 10:42:55.000000000 +0000 @@ -1,114 +1,126 @@ -############################################################################### -# Makefile script for Membw tool -# -# @par -# BSD LICENSE -# -# Copyright(c) 2018-2019 Intel Corporation. All rights reserved. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Intel Corporation nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -############################################################################### - -APP = membw - -CFLAGS=-W -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes \ - -Wmissing-declarations -Wold-style-definition -Wpointer-arith \ - -Wcast-qual -Wundef -Wwrite-strings \ - -Wformat -Wformat-security -fstack-protector -fPIE \ - -Wunreachable-code -Wsign-compare -Wno-endif-labels \ - -Winline -mavx512f - -ifeq ($(DEBUG),y) -CFLAGS += -O0 -g -DDEBUG -else -CFLAGS += -O3 -g -D_FORTIFY_SOURCE=2 -endif - -IS_GCC = $(shell $(CC) -v 2>&1 | grep -c "^gcc version ") -# GCC-only options -ifeq ($(IS_GCC),1) -CFLAGS += -fno-strict-overflow \ - -fno-delete-null-pointer-checks \ - -fwrapv -endif - -SRCS = $(sort $(wildcard *.c)) -OBJS = $(SRCS:.c=.o) -DEPFILES = $(SRCS:.c=.d) - -all: $(APP) - -$(APP): $(OBJS) - $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ - -%.o: %.c %.d - -%.d: %.c - $(CC) -MM -MP -MF $@ $(CFLAGS) $< - cat $@ | sed 's/$(@:.d=.o)/$@/' >> $@ - -.PHONY: clean - -clean: - -rm -f $(APP) $(OBJS) $(DEPFILES) ./*~ - -CHECKPATCH?=checkpatch.pl -.PHONY: checkpatch -checkpatch: - $(CHECKPATCH) --no-tree --no-signoff --emacs \ - --ignore CODE_INDENT,INITIALISED_STATIC,LEADING_SPACE \ - --ignore SPLIT_STRING,UNSPECIFIED_INT,ARRAY_SIZE,COMPLEX_MACRO \ - --ignore STORAGE_CLASS,SPDX_LICENSE_TAG,CONST_STRUCT \ - -f membw.c - -.PHONY: clang-format -clang-format: - @for file in $(wildcard *.[ch]); do \ - echo "Checking style $$file"; \ - clang-format -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ - { echo "ERROR: $$file has style problems"; exit 1; } \ - done - -.PHONY: style -style: - $(MAKE) checkpatch - $(MAKE) clang-format - -CPPCHECK?=cppcheck -.PHONY: cppcheck -cppcheck: - $(CPPCHECK) enable=warning,portability,performance,unusedFunction,missingInclude \ - --std=c99 --template=gcc membw.c - - -# if target not clean then make dependencies -ifneq ($(MAKECMDGOALS),clean) --include $(DEPFILES) -endif - +############################################################################### +# Makefile script for Membw tool +# +# @par +# BSD LICENSE +# +# Copyright(c) 2018-2020 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +############################################################################### + +APP = membw + +CFLAGS=-W -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes \ + -Wmissing-declarations -Wold-style-definition -Wpointer-arith \ + -Wcast-qual -Wundef -Wwrite-strings \ + -Wformat -Wformat-security -fstack-protector -fPIE \ + -Wunreachable-code -Wsign-compare -Wno-endif-labels \ + -Winline -msse4.2 + +ifeq ($(DEBUG),y) +CFLAGS += -O0 -g -DDEBUG +else +CFLAGS += -O3 -g -D_FORTIFY_SOURCE=2 +endif + +HAS_AVX512 := $(shell $(CC) -mavx512f -dM -E - < /dev/null 2> /dev/null | grep -c "AVX512F") +ifeq ($(HAS_AVX512),1) +CFLAGS += -mavx512f +endif + +HAS_CLWB := $(shell $(CC) -mclwb -dM -E - < /dev/null 2> /dev/null | grep -c "CLWB") +ifeq ($(HAS_CLWB),1) +CFLAGS += -mclwb +endif + +IS_GCC = $(shell $(CC) -v 2>&1 | grep -c "^gcc version ") +# GCC-only options +ifeq ($(IS_GCC),1) +CFLAGS += -fno-strict-overflow \ + -fno-delete-null-pointer-checks \ + -fwrapv \ + -fno-expensive-optimizations +endif + +SRCS = $(sort $(wildcard *.c)) +OBJS = $(SRCS:.c=.o) +DEPFILES = $(SRCS:.c=.d) + +all: $(APP) + +$(APP): $(OBJS) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +%.o: %.c %.d + +%.d: %.c + $(CC) -MM -MP -MF $@ $(CFLAGS) $< + cat $@ | sed 's/$(@:.d=.o)/$@/' >> $@ + +.PHONY: clean + +clean: + -rm -f $(APP) $(OBJS) $(DEPFILES) ./*~ + +CHECKPATCH?=checkpatch.pl +.PHONY: checkpatch +checkpatch: + $(CHECKPATCH) --no-tree --no-signoff --emacs \ + --ignore CODE_INDENT,INITIALISED_STATIC,LEADING_SPACE \ + --ignore SPLIT_STRING,UNSPECIFIED_INT,ARRAY_SIZE,COMPLEX_MACRO \ + --ignore STORAGE_CLASS,SPDX_LICENSE_TAG,CONST_STRUCT \ + -f membw.c + +CLANGFORMAT?=clang-format +.PHONY: clang-format +clang-format: + @for file in $(wildcard *.[ch]); do \ + echo "Checking style $$file"; \ + $(CLANGFORMAT) -style=file "$$file" | diff "$$file" - | tee /dev/stderr | [ $$(wc -c) -eq 0 ] || \ + { echo "ERROR: $$file has style problems"; exit 1; } \ + done + +.PHONY: style +style: + $(MAKE) checkpatch + $(MAKE) clang-format + +CPPCHECK?=cppcheck +.PHONY: cppcheck +cppcheck: + $(CPPCHECK) enable=warning,portability,performance,unusedFunction,missingInclude \ + --std=c99 --template=gcc membw.c + + +# if target not clean then make dependencies +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPFILES) +endif + diff -Nru intel-cmt-cat-3.2/tools/membw/membw.c intel-cmt-cat-4.0/tools/membw/membw.c --- intel-cmt-cat-3.2/tools/membw/membw.c 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tools/membw/membw.c 2020-06-19 10:42:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2018-2019 Intel Corporation. All rights reserved. + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,8 +64,8 @@ #endif #define MEMCHUNK_SIZE (PAGE_SIZE * 32 * 1024) /* 128MB chunk */ -#define CL_SIZE (64) -#define CHUNKS (128) +#define CL_SIZE (64) +#define CHUNKS (128) #ifdef DEBUG #include @@ -79,8 +79,8 @@ #define MAX_MEM_BW 100 * 1000 /* 100GBps */ -#define CPU_FEATURE_SSE4_2 (1ULL << 0) -#define CPU_FEATURE_CLWB (1ULL << 1) +#define CPU_FEATURE_SSE4_2 (1ULL << 0) +#define CPU_FEATURE_CLWB (1ULL << 1) #define CPU_FEATURE_AVX512F (1ULL << 2) /** @@ -446,6 +446,7 @@ } #ifdef __x86_64__ +#ifdef __AVX512F__ /** * @brief WB store vector version * @@ -461,6 +462,7 @@ : "r"(v), "r"(p) : "%zmm1", "memory"); } +#endif /** * @brief WB vector version @@ -539,6 +541,7 @@ #endif } +#ifdef __CLWB__ /** * @brief Perform write operation to specified cache line with clwb * @@ -551,6 +554,7 @@ cl_write(p, v); cl_wb(p); } +#endif /** * @brief Perform write operation to specified cache line with flush @@ -612,7 +616,7 @@ #endif } -#ifdef __x86_64__ +#if defined(__x86_64__) && defined(__AVX512F__) /** * @brief non-temporal store vector version * @@ -630,6 +634,7 @@ } #endif +#ifdef __CLWB__ /** * @brief Perform write operation to memory giving non-temporal hint with cache * line write back @@ -643,6 +648,7 @@ cl_write_nti(p, v); cl_wb(p); } +#endif #ifdef __x86_64__ /** @@ -803,27 +809,33 @@ case CL_TYPE_WRITE_WB: cl_write(ptr, val); break; -#ifdef __x86_64__ +#if defined(__x86_64__) && defined(__AVX512F__) case CL_TYPE_WRITE_WB_AVX512: cl_write_avx512(ptr, val); break; #endif +#ifdef __CLWB__ case CL_TYPE_WRITE_WB_CLWB: cl_write_clwb(ptr, val); break; +#endif case CL_TYPE_WRITE_WB_FLUSH: cl_write_flush(ptr, val); break; case CL_TYPE_WRITE_NTI: cl_write_nti(ptr, val); break; +#ifdef __CLWB__ case CL_TYPE_WRITE_NTI_CLWB: cl_write_nti_clwb(ptr, val); break; +#endif #ifdef __x86_64__ +#ifdef __AVX512F__ case CL_TYPE_WRITE_NT512: cl_write_nt512(ptr, val); break; +#endif case CL_TYPE_WRITE_NTDQ: cl_write_ntdq(ptr, val); break; @@ -916,15 +928,10 @@ { struct timespec req, rem; - memset(&rem, 0, sizeof(rem)); - memset(&req, 0, sizeof(req)); req.tv_sec = (interval - usec_diff) / 1000000L; req.tv_nsec = ((interval - usec_diff) % 1000000L) * 1000L; - if (nanosleep(&req, &rem) == -1) { - req = rem; - memset(&rem, 0, sizeof(rem)); - nanosleep(&req, &rem); - } + if (nanosleep(&req, &rem) == -1) + nanosleep(&rem, NULL); } /** @@ -1088,18 +1095,28 @@ break; case CL_TYPE_WRITE_NTI_CLWB: case CL_TYPE_WRITE_WB_CLWB: +#ifdef __CLWB__ if (!(features & CPU_FEATURE_CLWB)) { - printf("No CPU support for CLWB instruction!\n"); + printf("No CPU support for CLWB instructions!\n"); return EXIT_FAILURE; } +#else + printf("No compiler support for CLWB instructions!\n"); + return EXIT_FAILURE; +#endif break; #ifdef __x86_64__ case CL_TYPE_WRITE_NT512: case CL_TYPE_WRITE_WB_AVX512: +#ifdef __AVX512F__ if (!(features & CPU_FEATURE_AVX512F)) { printf("No CPU support for AVX512 instructions!\n"); return EXIT_FAILURE; } +#else + printf("No compiler support for AVX512 instructions!\n"); + return EXIT_FAILURE; +#endif break; #endif default: diff -Nru intel-cmt-cat-3.2/tools/membw/README intel-cmt-cat-4.0/tools/membw/README --- intel-cmt-cat-3.2/tools/membw/README 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/tools/membw/README 2020-06-19 10:42:55.000000000 +0000 @@ -25,9 +25,6 @@ Requirements and Installation ============================= -Note: The membw tool requires compiler support for AVX512 instructions. - For GCC, this is version 4.9 or above. - For installation of the Intel(R) Membw tool follow below instructions: To compile: diff -Nru intel-cmt-cat-3.2/.travis.yml intel-cmt-cat-4.0/.travis.yml --- intel-cmt-cat-3.2/.travis.yml 2019-12-19 09:58:52.000000000 +0000 +++ intel-cmt-cat-4.0/.travis.yml 2020-06-19 10:42:55.000000000 +0000 @@ -2,12 +2,13 @@ dist: bionic before_script: - sudo apt-get -q update - - sudo apt-get install -y swig cppcheck wget python3-virtualenv clang-format - - wget -P /tmp/ https://raw.githubusercontent.com/torvalds/linux/879be4f378cb412af3a3fe107d35835c99099add/scripts/checkpatch.pl && chmod a+x /tmp/checkpatch.pl - - wget -P /tmp/ https://raw.githubusercontent.com/torvalds/linux/879be4f378cb412af3a3fe107d35835c99099add/scripts/spelling.txt + - sudo apt-get install -y swig cppcheck wget python3-virtualenv clang-format-9 + - wget -P /tmp/ https://raw.githubusercontent.com/torvalds/linux/184b8f7f91ca7938c09533df83ce84817e682975/scripts/checkpatch.pl && chmod a+x /tmp/checkpatch.pl + - wget -P /tmp/ https://raw.githubusercontent.com/torvalds/linux/184b8f7f91ca7938c09533df83ce84817e682975/scripts/spelling.txt + - wget -P /tmp/ https://raw.githubusercontent.com/torvalds/linux/184b8f7f91ca7938c09533df83ce84817e682975/scripts/const_structs.checkpatch script: - make cppcheck - - make style CHECKPATCH=/tmp/checkpatch.pl + - make style CHECKPATCH=/tmp/checkpatch.pl CLANGFORMAT=clang-format-9 - make - sudo make install - LD_LIBRARY_PATH=`pwd`/lib make -C lib/python test