First Push
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __DETECT_SELF_HOSTED_H__
|
||||
#define __DETECT_SELF_HOSTED_H__
|
||||
|
||||
// PCI devIds 0x2340-0x237f are for Self-Hosted Hopper
|
||||
static inline int pci_devid_is_self_hosted(unsigned short devid)
|
||||
{
|
||||
return devid >= 0x2340 && devid <= 0x237f;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
+211
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_AEAD_H
|
||||
#define CRYPTLIB_AEAD_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Authenticated Encryption with Associated data (AEAD) Cryptography Primitives
|
||||
*=====================================================================================
|
||||
*/
|
||||
|
||||
#if LIBSPDM_AEAD_GCM_SUPPORT
|
||||
/**
|
||||
* Performs AEAD AES-GCM authenticated encryption on a data buffer and additional authenticated
|
||||
* data.
|
||||
*
|
||||
* iv_size must be 12, otherwise false is returned.
|
||||
* key_size must be 16 or 32, otherwise false is returned.
|
||||
* tag_size must be 12, 13, 14, 15, 16, otherwise false is returned.
|
||||
*
|
||||
* @param[in] key Pointer to the encryption key.
|
||||
* @param[in] key_size Size of the encryption key in bytes.
|
||||
* @param[in] iv Pointer to the IV value.
|
||||
* @param[in] iv_size Size of the IV value in bytes.
|
||||
* @param[in] a_data Pointer to the additional authenticated data.
|
||||
* @param[in] a_data_size Size of the additional authenticated data in bytes.
|
||||
* @param[in] data_in Pointer to the input data buffer to be encrypted.
|
||||
* @param[in] data_in_size Size of the input data buffer in bytes.
|
||||
* @param[out] tag_out Pointer to a buffer that receives the authentication tag output.
|
||||
* @param[in] tag_size Size of the authentication tag in bytes.
|
||||
* @param[out] data_out Pointer to a buffer that receives the encryption output.
|
||||
* @param[out] data_out_size Size of the output data buffer in bytes.
|
||||
*
|
||||
* @retval true AEAD AES-GCM authenticated encryption succeeded.
|
||||
* @retval false AEAD AES-GCM authenticated encryption failed.
|
||||
**/
|
||||
extern bool libspdm_aead_aes_gcm_encrypt(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag_out, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size);
|
||||
|
||||
/**
|
||||
* Performs AEAD AES-GCM authenticated decryption on a data buffer and additional authenticated
|
||||
* data.
|
||||
*
|
||||
* iv_size must be 12, otherwise false is returned.
|
||||
* key_size must be 16 or 32, otherwise false is returned.
|
||||
* tag_size must be 12, 13, 14, 15, 16, otherwise false is returned.
|
||||
*
|
||||
* If data verification fails, false is returned.
|
||||
*
|
||||
* @param[in] key Pointer to the encryption key.
|
||||
* @param[in] key_size Size of the encryption key in bytes.
|
||||
* @param[in] iv Pointer to the IV value.
|
||||
* @param[in] iv_size Size of the IV value in bytes.
|
||||
* @param[in] a_data Pointer to the additional authenticated data.
|
||||
* @param[in] a_data_size Size of the additional authenticated data in bytes.
|
||||
* @param[in] data_in Pointer to the input data buffer to be decrypted.
|
||||
* @param[in] data_in_size Size of the input data buffer in bytes.
|
||||
* @param[in] tag Pointer to a buffer that contains the authentication tag.
|
||||
* @param[in] tag_size Size of the authentication tag in bytes.
|
||||
* @param[out] data_out Pointer to a buffer that receives the decryption output.
|
||||
* @param[out] data_out_size Size of the output data buffer in bytes.
|
||||
*
|
||||
* @retval true AEAD AES-GCM authenticated decryption succeeded.
|
||||
* @retval false AEAD AES-GCM authenticated decryption failed.
|
||||
**/
|
||||
extern bool libspdm_aead_aes_gcm_decrypt(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size);
|
||||
#endif /* LIBSPDM_AEAD_GCM_SUPPORT */
|
||||
|
||||
#if LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT
|
||||
/**
|
||||
* Performs AEAD ChaCha20Poly1305 authenticated encryption on a data buffer and additional
|
||||
* authenticated data.
|
||||
*
|
||||
* iv_size must be 12, otherwise false is returned.
|
||||
* key_size must be 32, otherwise false is returned.
|
||||
* tag_size must be 16, otherwise false is returned.
|
||||
*
|
||||
* @param[in] key Pointer to the encryption key.
|
||||
* @param[in] key_size Size of the encryption key in bytes.
|
||||
* @param[in] iv Pointer to the IV value.
|
||||
* @param[in] iv_size Size of the IV value in bytes.
|
||||
* @param[in] a_data Pointer to the additional authenticated data.
|
||||
* @param[in] a_data_size Size of the additional authenticated data in bytes.
|
||||
* @param[in] data_in Pointer to the input data buffer to be encrypted.
|
||||
* @param[in] data_in_size Size of the input data buffer in bytes.
|
||||
* @param[out] tag_out Pointer to a buffer that receives the authentication tag output.
|
||||
* @param[in] tag_size Size of the authentication tag in bytes.
|
||||
* @param[out] data_out Pointer to a buffer that receives the encryption output.
|
||||
* @param[out] data_out_size Size of the output data buffer in bytes.
|
||||
*
|
||||
* @retval true AEAD ChaCha20Poly1305 authenticated encryption succeeded.
|
||||
* @retval false AEAD ChaCha20Poly1305 authenticated encryption failed.
|
||||
**/
|
||||
extern bool libspdm_aead_chacha20_poly1305_encrypt(
|
||||
const uint8_t *key, size_t key_size, const uint8_t *iv,
|
||||
size_t iv_size, const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size, uint8_t *tag_out,
|
||||
size_t tag_size, uint8_t *data_out, size_t *data_out_size);
|
||||
|
||||
/**
|
||||
* Performs AEAD ChaCha20Poly1305 authenticated decryption on a data buffer and additional authenticated data (AAD).
|
||||
*
|
||||
* iv_size must be 12, otherwise false is returned.
|
||||
* key_size must be 32, otherwise false is returned.
|
||||
* tag_size must be 16, otherwise false is returned.
|
||||
*
|
||||
* If data verification fails, false is returned.
|
||||
*
|
||||
* @param[in] key Pointer to the encryption key.
|
||||
* @param[in] key_size Size of the encryption key in bytes.
|
||||
* @param[in] iv Pointer to the IV value.
|
||||
* @param[in] iv_size Size of the IV value in bytes.
|
||||
* @param[in] a_data Pointer to the additional authenticated data.
|
||||
* @param[in] a_data_size Size of the additional authenticated data in bytes.
|
||||
* @param[in] data_in Pointer to the input data buffer to be decrypted.
|
||||
* @param[in] data_in_size Size of the input data buffer in bytes.
|
||||
* @param[in] tag Pointer to a buffer that contains the authentication tag.
|
||||
* @param[in] tag_size Size of the authentication tag in bytes.
|
||||
* @param[out] data_out Pointer to a buffer that receives the decryption output.
|
||||
* @param[out] data_out_size Size of the output data buffer in bytes.
|
||||
*
|
||||
* @retval true AEAD ChaCha20Poly1305 authenticated decryption succeeded.
|
||||
* @retval false AEAD ChaCha20Poly1305 authenticated decryption failed.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_aead_chacha20_poly1305_decrypt(
|
||||
const uint8_t *key, size_t key_size, const uint8_t *iv,
|
||||
size_t iv_size, const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size, const uint8_t *tag,
|
||||
size_t tag_size, uint8_t *data_out, size_t *data_out_size);
|
||||
#endif /* LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT */
|
||||
|
||||
#if LIBSPDM_AEAD_SM4_SUPPORT
|
||||
/**
|
||||
* Performs AEAD SM4-GCM authenticated encryption on a data buffer and additional authenticated
|
||||
* data.
|
||||
*
|
||||
* iv_size must be 12, otherwise false is returned.
|
||||
* key_size must be 16, otherwise false is returned.
|
||||
* tag_size must be 16, otherwise false is returned.
|
||||
*
|
||||
* @param[in] key Pointer to the encryption key.
|
||||
* @param[in] key_size Size of the encryption key in bytes.
|
||||
* @param[in] iv Pointer to the IV value.
|
||||
* @param[in] iv_size Size of the IV value in bytes.
|
||||
* @param[in] a_data Pointer to the additional authenticated data.
|
||||
* @param[in] a_data_size Size of the additional authenticated data in bytes.
|
||||
* @param[in] data_in Pointer to the input data buffer to be encrypted.
|
||||
* @param[in] data_in_size Size of the input data buffer in bytes.
|
||||
* @param[out] tag_out Pointer to a buffer that receives the authentication tag output.
|
||||
* @param[in] tag_size Size of the authentication tag in bytes.
|
||||
* @param[out] data_out Pointer to a buffer that receives the encryption output.
|
||||
* @param[out] data_out_size Size of the output data buffer in bytes.
|
||||
*
|
||||
* @retval true AEAD SM4-GCM authenticated encryption succeeded.
|
||||
* @retval false AEAD SM4-GCM authenticated encryption failed.
|
||||
**/
|
||||
extern bool libspdm_aead_sm4_gcm_encrypt(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag_out, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size);
|
||||
|
||||
/**
|
||||
* Performs AEAD SM4-GCM authenticated decryption on a data buffer and additional authenticated
|
||||
* data.
|
||||
*
|
||||
* iv_size must be 12, otherwise false is returned.
|
||||
* key_size must be 16, otherwise false is returned.
|
||||
* tag_size must be 16, otherwise false is returned.
|
||||
*
|
||||
* If data verification fails, false is returned.
|
||||
*
|
||||
* @param[in] key Pointer to the encryption key.
|
||||
* @param[in] key_size Size of the encryption key in bytes.
|
||||
* @param[in] iv Pointer to the IV value.
|
||||
* @param[in] iv_size Size of the IV value in bytes.
|
||||
* @param[in] a_data Pointer to the additional authenticated data.
|
||||
* @param[in] a_data_size Size of the additional authenticated data in bytes.
|
||||
* @param[in] data_in Pointer to the input data buffer to be decrypted.
|
||||
* @param[in] data_in_size Size of the input data buffer in bytes.
|
||||
* @param[in] tag Pointer to a buffer that contains the authentication tag.
|
||||
* @param[in] tag_size Size of the authentication tag in bytes.
|
||||
* @param[out] data_out Pointer to a buffer that receives the decryption output.
|
||||
* @param[out] data_out_size Size of the output data buffer in bytes.
|
||||
*
|
||||
* @retval true AEAD SM4-GCM authenticated decryption succeeded.
|
||||
* @retval false AEAD SM4-GCM authenticated decryption failed.
|
||||
**/
|
||||
extern bool libspdm_aead_sm4_gcm_decrypt(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size);
|
||||
#endif /* LIBSPDM_AEAD_SM4_SUPPORT */
|
||||
|
||||
#endif /* CRYPTLIB_AEAD_H */
|
||||
+416
@@ -0,0 +1,416 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_CERT_H
|
||||
#define CRYPTLIB_CERT_H
|
||||
|
||||
/**
|
||||
* Retrieve the tag and length of the tag.
|
||||
*
|
||||
* @param ptr The position in the ASN.1 data.
|
||||
* @param end End of data.
|
||||
* @param length The variable that will receive the length.
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @retval true Get tag successful.
|
||||
* @retval false Failed to get tag or tag not match.
|
||||
**/
|
||||
extern bool libspdm_asn1_get_tag(uint8_t **ptr, const uint8_t *end, size_t *length, uint32_t tag);
|
||||
|
||||
/**
|
||||
* Retrieve the subject bytes from one X.509 certificate.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If subject_size is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] cert_subject Pointer to the retrieved certificate subject bytes.
|
||||
* @param[in, out] subject_size The size in bytes of the cert_subject buffer on input,
|
||||
* and the size of buffer returned cert_subject on output.
|
||||
*
|
||||
* @retval true The certificate subject retrieved successfully.
|
||||
* @retval false Invalid certificate, or the subject_size is too small for the result.
|
||||
* The subject_size will be updated with the required size.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_x509_get_subject_name(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *cert_subject,
|
||||
size_t *subject_size);
|
||||
|
||||
/**
|
||||
* Retrieve the version from one X.509 certificate.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If cert_size is 0, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] version Pointer to the retrieved version integer.
|
||||
*
|
||||
* @retval true
|
||||
* @retval false
|
||||
**/
|
||||
extern bool libspdm_x509_get_version(const uint8_t *cert, size_t cert_size, size_t *version);
|
||||
|
||||
/**
|
||||
* Retrieve the serialNumber from one X.509 certificate.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If cert_size is 0, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] serial_number Pointer to the retrieved certificate serial_number bytes.
|
||||
* @param[in, out] serial_number_size The size in bytes of the serial_number buffer on input,
|
||||
* and the size of buffer returned serial_number on output.
|
||||
*
|
||||
* @retval true
|
||||
* @retval false
|
||||
**/
|
||||
extern bool libspdm_x509_get_serial_number(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *serial_number,
|
||||
size_t *serial_number_size);
|
||||
|
||||
/**
|
||||
* Retrieve the issuer bytes from one X.509 certificate.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If issuer_size is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] cert_issuer Pointer to the retrieved certificate subject bytes.
|
||||
* @param[in, out] issuer_size The size in bytes of the cert_issuer buffer on input,
|
||||
* and the size of buffer returned cert_issuer on output.
|
||||
*
|
||||
* @retval true The certificate issuer retrieved successfully.
|
||||
* @retval false Invalid certificate, or the issuer_size is too small for the result.
|
||||
* The issuer_size will be updated with the required size.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_x509_get_issuer_name(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *cert_issuer,
|
||||
size_t *issuer_size);
|
||||
|
||||
/**
|
||||
* Retrieve Extension data from one X.509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[in] oid Object identifier buffer
|
||||
* @param[in] oid_size Object identifier buffer size
|
||||
* @param[out] extension_data Extension bytes.
|
||||
* @param[in, out] extension_data_size Extension bytes size.
|
||||
*
|
||||
* @retval true
|
||||
* @retval false
|
||||
**/
|
||||
extern bool libspdm_x509_get_extension_data(const uint8_t *cert, size_t cert_size,
|
||||
const uint8_t *oid, size_t oid_size,
|
||||
uint8_t *extension_data,
|
||||
size_t *extension_data_size);
|
||||
|
||||
/**
|
||||
* Retrieve the Validity from one X.509 certificate
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If CertIssuerSize is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] from notBefore Pointer to date_time object.
|
||||
* @param[in,out] from_size notBefore date_time object size.
|
||||
* @param[out] to notAfter Pointer to date_time object.
|
||||
* @param[in,out] to_size notAfter date_time object size.
|
||||
*
|
||||
* Note: libspdm_x509_compare_date_time to compare date_time oject
|
||||
* x509SetDateTime to get a date_time object from a date_time_str
|
||||
*
|
||||
* @retval true The certificate Validity retrieved successfully.
|
||||
* @retval false Invalid certificate, or Validity retrieve failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_x509_get_validity(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *from, size_t *from_size, uint8_t *to,
|
||||
size_t *to_size);
|
||||
|
||||
/**
|
||||
* Format a date_time object into DataTime buffer
|
||||
*
|
||||
* If date_time_str is NULL, then return false.
|
||||
* If date_time_size is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] date_time_str date_time string like YYYYMMDDhhmmssZ
|
||||
* Ref: https://www.w3.org/TR/NOTE-datetime
|
||||
* Z stand for UTC time
|
||||
* @param[out] date_time Pointer to a date_time object.
|
||||
* @param[in,out] date_time_size date_time object buffer size.
|
||||
*
|
||||
* @retval true
|
||||
* @retval false
|
||||
**/
|
||||
extern bool libspdm_x509_set_date_time(const char *date_time_str, void *date_time,
|
||||
size_t *date_time_size);
|
||||
|
||||
/**
|
||||
* Compare date_time1 object and date_time2 object.
|
||||
*
|
||||
* If date_time1 is NULL, then return -2.
|
||||
* If date_time2 is NULL, then return -2.
|
||||
* If date_time1 == date_time2, then return 0
|
||||
* If date_time1 > date_time2, then return 1
|
||||
* If date_time1 < date_time2, then return -1
|
||||
*
|
||||
* @param[in] date_time1 Pointer to a date_time Ojbect
|
||||
* @param[in] date_time2 Pointer to a date_time Object
|
||||
*
|
||||
* @retval 0 If date_time1 == date_time2
|
||||
* @retval 1 If date_time1 > date_time2
|
||||
* @retval -1 If date_time1 < date_time2
|
||||
**/
|
||||
extern int32_t libspdm_x509_compare_date_time(const void *date_time1, const void *date_time2);
|
||||
|
||||
/**
|
||||
* Retrieve the key usage from one X.509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] usage Key usage (LIBSPDM_CRYPTO_X509_KU_*)
|
||||
*
|
||||
* @retval true The certificate key usage retrieved successfully.
|
||||
* @retval false Invalid certificate, or usage is NULL
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_x509_get_key_usage(const uint8_t *cert, size_t cert_size, size_t *usage);
|
||||
|
||||
/**
|
||||
* Retrieve the Extended key usage from one X.509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] usage Key usage bytes.
|
||||
* @param[in, out] usage_size Key usage buffer sizs in bytes.
|
||||
*
|
||||
* @retval true
|
||||
* @retval false
|
||||
**/
|
||||
extern bool libspdm_x509_get_extended_key_usage(const uint8_t *cert,
|
||||
size_t cert_size, uint8_t *usage,
|
||||
size_t *usage_size);
|
||||
|
||||
/**
|
||||
* Retrieve the basic constraints from one X.509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] basic_constraints Basic constraints bytes.
|
||||
* @param[in, out] basic_constraints_size Basic constraints buffer sizs in bytes.
|
||||
*
|
||||
* @retval true
|
||||
* @retval false
|
||||
**/
|
||||
extern bool libspdm_x509_get_extended_basic_constraints(const uint8_t *cert,
|
||||
size_t cert_size,
|
||||
uint8_t *basic_constraints,
|
||||
size_t *basic_constraints_size);
|
||||
|
||||
/**
|
||||
* Verify one X509 certificate was issued by the trusted CA.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If ca_cert is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate to be verified.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[in] ca_cert Pointer to the DER-encoded trusted CA certificate.
|
||||
* @param[in] ca_cert_size Size of the CA Certificate in bytes.
|
||||
*
|
||||
* @retval true The certificate was issued by the trusted CA.
|
||||
* @retval false Invalid certificate or the certificate was not issued by the given
|
||||
* trusted CA.
|
||||
* @retval false This interface is not supported.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_x509_verify_cert(const uint8_t *cert, size_t cert_size,
|
||||
const uint8_t *ca_cert, size_t ca_cert_size);
|
||||
|
||||
/**
|
||||
* Verify one X509 certificate was issued by the trusted CA.
|
||||
*
|
||||
* @param[in] cert_chain One or more ASN.1 DER-encoded X.509 certificates
|
||||
* where the first certificate is signed by the Root
|
||||
* Certificate or is the Root Cerificate itself. and
|
||||
* subsequent cerificate is signed by the preceding
|
||||
* cerificate.
|
||||
* @param[in] cert_chain_length Total length of the certificate chain, in bytes.
|
||||
*
|
||||
* @param[in] root_cert Trusted Root Certificate buffer.
|
||||
*
|
||||
* @param[in] root_cert_length Trusted Root Certificate buffer length.
|
||||
*
|
||||
* @retval true All cerificates were issued by the first certificate in X509Certchain.
|
||||
* @retval false Invalid certificate or the certificate was not issued by the given
|
||||
* trusted CA.
|
||||
**/
|
||||
extern bool libspdm_x509_verify_cert_chain(const uint8_t *root_cert, size_t root_cert_length,
|
||||
const uint8_t *cert_chain,
|
||||
size_t cert_chain_length);
|
||||
|
||||
/**
|
||||
* Get one X509 certificate from cert_chain.
|
||||
*
|
||||
* @param[in] cert_chain One or more ASN.1 DER-encoded X.509 certificates
|
||||
* where the first certificate is signed by the Root
|
||||
* Certificate or is the Root Cerificate itself. and
|
||||
* subsequent cerificate is signed by the preceding
|
||||
* cerificate.
|
||||
* @param[in] cert_chain_length Total length of the certificate chain, in bytes.
|
||||
*
|
||||
* @param[in] cert_index Index of certificate. If index is -1 indecate the
|
||||
* last certificate in cert_chain.
|
||||
*
|
||||
* @param[out] cert The certificate at the index of cert_chain.
|
||||
* @param[out] cert_length The length certificate at the index of cert_chain.
|
||||
*
|
||||
* @retval true Success.
|
||||
* @retval false Failed to get certificate from certificate chain.
|
||||
**/
|
||||
extern bool libspdm_x509_get_cert_from_cert_chain(const uint8_t *cert_chain,
|
||||
size_t cert_chain_length,
|
||||
const int32_t cert_index, const uint8_t **cert,
|
||||
size_t *cert_length);
|
||||
|
||||
#if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
|
||||
/**
|
||||
* Retrieve the RSA public key from one DER-encoded X509 certificate.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] rsa_context Pointer to new-generated RSA context which contain the retrieved
|
||||
* RSA public key component. Use libspdm_rsa_free() function to free the
|
||||
* resource.
|
||||
*
|
||||
* @retval true RSA public key was retrieved successfully.
|
||||
* @retval false Fail to retrieve RSA public key from X509 certificate.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_rsa_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **rsa_context);
|
||||
#endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
|
||||
|
||||
#if LIBSPDM_ECDSA_SUPPORT
|
||||
/**
|
||||
* Retrieve the EC public key from one DER-encoded X509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] ec_context Pointer to new-generated EC DSA context which contain the retrieved
|
||||
* EC public key component. Use libspdm_ec_free() function to free the
|
||||
* resource.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If ec_context is NULL, then return false.
|
||||
*
|
||||
* @retval true EC public key was retrieved successfully.
|
||||
* @retval false Fail to retrieve EC public key from X509 certificate.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_ec_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **ec_context);
|
||||
#endif /* LIBSPDM_ECDSA_SUPPORT */
|
||||
|
||||
#if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
|
||||
/**
|
||||
* Retrieve the Ed public key from one DER-encoded X509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] ecd_context Pointer to new-generated Ed DSA context which contain the retrieved
|
||||
* Ed public key component. Use libspdm_ecd_free() function to free the
|
||||
* resource.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If ecd_context is NULL, then return false.
|
||||
*
|
||||
* @retval true Ed public key was retrieved successfully.
|
||||
* @retval false Fail to retrieve Ed public key from X509 certificate.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_ecd_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **ecd_context);
|
||||
#endif /* (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT) */
|
||||
|
||||
#if LIBSPDM_SM2_DSA_SUPPORT
|
||||
/**
|
||||
* Retrieve the sm2 public key from one DER-encoded X509 certificate.
|
||||
*
|
||||
* @param[in] cert Pointer to the DER-encoded X509 certificate.
|
||||
* @param[in] cert_size Size of the X509 certificate in bytes.
|
||||
* @param[out] sm2_context Pointer to new-generated sm2 context which contain the retrieved
|
||||
* sm2 public key component. Use sm2_free() function to free the
|
||||
* resource.
|
||||
*
|
||||
* If cert is NULL, then return false.
|
||||
* If sm2_context is NULL, then return false.
|
||||
*
|
||||
* @retval true sm2 public key was retrieved successfully.
|
||||
* @retval false Fail to retrieve sm2 public key from X509 certificate.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_sm2_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **sm2_context);
|
||||
#endif /* LIBSPDM_SM2_DSA_SUPPORT */
|
||||
|
||||
#if LIBSPDM_ENABLE_CAPABILITY_GET_CSR_CAP
|
||||
/**
|
||||
* Generate a CSR.
|
||||
*
|
||||
* @param[in] hash_nid hash algo for sign
|
||||
* @param[in] asym_nid asym algo for sign
|
||||
*
|
||||
* @param[in] requester_info requester info to gen CSR
|
||||
* @param[in] requester_info_length The len of requester info
|
||||
*
|
||||
* @param[in] context Pointer to asymmetric context
|
||||
* @param[in] subject_name Subject name: should be break with ',' in the middle
|
||||
* example: "C=AA,CN=BB"
|
||||
*
|
||||
* Subject names should contain a comma-separated list of OID types and values:
|
||||
* The valid OID type name is in:
|
||||
* {"CN", "commonName", "C", "countryName", "O", "organizationName","L",
|
||||
* "OU", "organizationalUnitName", "ST", "stateOrProvinceName", "emailAddress",
|
||||
* "serialNumber", "postalAddress", "postalCode", "dnQualifier", "title",
|
||||
* "SN","givenName","GN", "initials", "pseudonym", "generationQualifier", "domainComponent", "DC"}.
|
||||
* Note: The object of C and countryName should be CSR Supported Country Codes
|
||||
*
|
||||
* @param[in] csr_len For input, csr_len is the size of store CSR buffer.
|
||||
* For output, csr_len is CSR len for DER format
|
||||
* @param[in] csr_pointer For input, csr_pointer is buffer address to store CSR.
|
||||
* For output, csr_pointer is address for stored CSR.
|
||||
* The csr_pointer address will be changed.
|
||||
*
|
||||
* @retval true Success.
|
||||
* @retval false Failed to gen CSR.
|
||||
**/
|
||||
extern bool libspdm_gen_x509_csr(size_t hash_nid, size_t asym_nid,
|
||||
uint8_t *requester_info, size_t requester_info_length,
|
||||
void *context, char *subject_name,
|
||||
size_t *csr_len, uint8_t **csr_pointer);
|
||||
#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_CSR_CAP */
|
||||
|
||||
#endif /* CRYPTLIB_CERT_H */
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_DH_H
|
||||
#define CRYPTLIB_DH_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Diffie-Hellman Key Exchange Primitives
|
||||
*=====================================================================================
|
||||
*/
|
||||
|
||||
#if LIBSPDM_FFDHE_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one Diffie-Hellman context for subsequent use with the NID.
|
||||
*
|
||||
* @param nid cipher NID
|
||||
*
|
||||
* @return Pointer to the Diffie-Hellman context that has been initialized.
|
||||
* If the allocations fails, libspdm_dh_new_by_nid() returns NULL.
|
||||
* If the interface is not supported, libspdm_dh_new_by_nid() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_dh_new_by_nid(size_t nid);
|
||||
|
||||
/**
|
||||
* Release the specified DH context.
|
||||
*
|
||||
* @param[in] dh_context Pointer to the DH context to be released.
|
||||
**/
|
||||
void libspdm_dh_free(void *dh_context);
|
||||
|
||||
/**
|
||||
* Generates DH public key.
|
||||
*
|
||||
* This function generates random secret exponent, and computes the public key, which is
|
||||
* returned via parameter public_key and public_key_size. DH context is updated accordingly.
|
||||
* If the public_key buffer is too small to hold the public key, false is returned and
|
||||
* public_key_size is set to the required buffer size to obtain the public key.
|
||||
*
|
||||
* If dh_context is NULL, then return false.
|
||||
* If public_key_size is NULL, then return false.
|
||||
* If public_key_size is large enough but public_key is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* For FFDHE2048, the public_size is 256.
|
||||
* For FFDHE3072, the public_size is 384.
|
||||
* For FFDHE4096, the public_size is 512.
|
||||
*
|
||||
* @param[in, out] dh_context Pointer to the DH context.
|
||||
* @param[out] public_key Pointer to the buffer to receive generated public key.
|
||||
* @param[in, out] public_key_size On input, the size of public_key buffer in bytes.
|
||||
* On output, the size of data returned in public_key buffer in
|
||||
* bytes.
|
||||
*
|
||||
* @retval true DH public key generation succeeded.
|
||||
* @retval false DH public key generation failed.
|
||||
* @retval false public_key_size is not large enough.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_dh_generate_key(void *dh_context, uint8_t *public_key, size_t *public_key_size);
|
||||
|
||||
/**
|
||||
* Computes exchanged common key.
|
||||
*
|
||||
* Given peer's public key, this function computes the exchanged common key, based on its own
|
||||
* context including value of prime modulus and random secret exponent.
|
||||
*
|
||||
* If dh_context is NULL, then return false.
|
||||
* If peer_public_key is NULL, then return false.
|
||||
* If key_size is NULL, then return false.
|
||||
* If key is NULL, then return false.
|
||||
* If key_size is not large enough, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* For FFDHE2048, the peer_public_size and key_size is 256.
|
||||
* For FFDHE3072, the peer_public_size and key_size is 384.
|
||||
* For FFDHE4096, the peer_public_size and key_size is 512.
|
||||
*
|
||||
* @param[in, out] dh_context Pointer to the DH context.
|
||||
* @param[in] peer_public_key Pointer to the peer's public key.
|
||||
* @param[in] peer_public_key_size size of peer's public key in bytes.
|
||||
* @param[out] key Pointer to the buffer to receive generated key.
|
||||
* @param[in, out] key_size On input, the size of key buffer in bytes.
|
||||
* On output, the size of data returned in key buffer in
|
||||
* bytes.
|
||||
*
|
||||
* @retval true DH exchanged key generation succeeded.
|
||||
* @retval false DH exchanged key generation failed.
|
||||
* @retval false key_size is not large enough.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_dh_compute_key(void *dh_context, const uint8_t *peer_public_key,
|
||||
size_t peer_public_key_size, uint8_t *key,
|
||||
size_t *key_size);
|
||||
#endif /* LIBSPDM_FFDHE_SUPPORT */
|
||||
#endif /* CRYPTLIB_DH_H */
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_EC_H
|
||||
#define CRYPTLIB_EC_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Elliptic Curve Primitives
|
||||
*=====================================================================================*/
|
||||
|
||||
#if (LIBSPDM_ECDHE_SUPPORT) || (LIBSPDM_ECDSA_SUPPORT)
|
||||
/**
|
||||
* Allocates and Initializes one Elliptic Curve context for subsequent use with the NID.
|
||||
*
|
||||
* @param nid cipher NID
|
||||
*
|
||||
* @return Pointer to the Elliptic Curve context that has been initialized.
|
||||
* If the allocations fails, libspdm_ec_new_by_nid() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_ec_new_by_nid(size_t nid);
|
||||
|
||||
/**
|
||||
* Release the specified EC context.
|
||||
*
|
||||
* @param[in] ec_context Pointer to the EC context to be released.
|
||||
**/
|
||||
extern void libspdm_ec_free(void *ec_context);
|
||||
#endif /* (LIBSPDM_ECDHE_SUPPORT) || (LIBSPDM_ECDSA_SUPPORT) */
|
||||
|
||||
#if LIBSPDM_ECDHE_SUPPORT
|
||||
/**
|
||||
* Generates EC key and returns EC public key (X, Y).
|
||||
*
|
||||
* This function generates random secret, and computes the public key (X, Y), which is
|
||||
* returned via parameter public, public_size.
|
||||
* X is the first half of public with size being public_size / 2,
|
||||
* Y is the second half of public with size being public_size / 2.
|
||||
* EC context is updated accordingly.
|
||||
* If the public buffer is too small to hold the public X, Y, false is returned and
|
||||
* public_size is set to the required buffer size to obtain the public X, Y.
|
||||
*
|
||||
* For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
|
||||
* For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
|
||||
* For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
|
||||
*
|
||||
* If ec_context is NULL, then return false.
|
||||
* If public_size is NULL, then return false.
|
||||
* If public_size is large enough but public is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] ec_context Pointer to the EC context.
|
||||
* @param[out] public Pointer to the buffer to receive generated public X,Y.
|
||||
* @param[in, out] public_size On input, the size of public buffer in bytes.
|
||||
* On output, the size of data returned in public buffer in bytes.
|
||||
*
|
||||
* @retval true EC public X,Y generation succeeded.
|
||||
* @retval false EC public X,Y generation failed.
|
||||
* @retval false public_size is not large enough.
|
||||
**/
|
||||
extern bool libspdm_ec_generate_key(void *ec_context, uint8_t *public_key, size_t *public_key_size);
|
||||
|
||||
/**
|
||||
* Computes exchanged common key.
|
||||
*
|
||||
* Given peer's public key (X, Y), this function computes the exchanged common key,
|
||||
* based on its own context including value of curve parameter and random secret.
|
||||
* X is the first half of peer_public with size being peer_public_size / 2,
|
||||
* Y is the second half of peer_public with size being peer_public_size / 2.
|
||||
*
|
||||
* If ec_context is NULL, then return false.
|
||||
* If peer_public is NULL, then return false.
|
||||
* If peer_public_size is 0, then return false.
|
||||
* If key is NULL, then return false.
|
||||
* If key_size is not large enough, then return false.
|
||||
*
|
||||
* For P-256, the peer_public_size is 64. first 32-byte is X, second 32-byte is Y.
|
||||
* The key_size is 32.
|
||||
* For P-384, the peer_public_size is 96. first 48-byte is X, second 48-byte is Y.
|
||||
* The key_size is 48.
|
||||
* For P-521, the peer_public_size is 132. first 66-byte is X, second 66-byte is Y.
|
||||
* The key_size is 66.
|
||||
*
|
||||
* @param[in, out] ec_context Pointer to the EC context.
|
||||
* @param[in] peer_public Pointer to the peer's public X,Y.
|
||||
* @param[in] peer_public_size Size of peer's public X,Y in bytes.
|
||||
* @param[out] key Pointer to the buffer to receive generated key.
|
||||
* @param[in, out] key_size On input, the size of key buffer in bytes.
|
||||
* On output, the size of data returned in key buffer in bytes.
|
||||
*
|
||||
* @retval true EC exchanged key generation succeeded.
|
||||
* @retval false EC exchanged key generation failed.
|
||||
* @retval false key_size is not large enough.
|
||||
**/
|
||||
extern bool libspdm_ec_compute_key(void *ec_context, const uint8_t *peer_public,
|
||||
size_t peer_public_size, uint8_t *key,
|
||||
size_t *key_size);
|
||||
#endif /* LIBSPDM_ECDHE_SUPPORT */
|
||||
|
||||
#if LIBSPDM_ECDSA_SUPPORT
|
||||
/**
|
||||
* Carries out the EC-DSA signature.
|
||||
*
|
||||
* This function carries out the EC-DSA signature.
|
||||
* If the signature buffer is too small to hold the contents of signature, false
|
||||
* is returned and sig_size is set to the required buffer size to obtain the signature.
|
||||
*
|
||||
* If ec_context is NULL, then return false.
|
||||
* If message_hash is NULL, then return false.
|
||||
* If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256,
|
||||
* SHA3_384, SHA3_512.
|
||||
* If sig_size is large enough but signature is NULL, then return false.
|
||||
*
|
||||
* For P-256, the sig_size is 64. first 32-byte is R, second 32-byte is S.
|
||||
* For P-384, the sig_size is 96. first 48-byte is R, second 48-byte is S.
|
||||
* For P-521, the sig_size is 132. first 66-byte is R, second 66-byte is S.
|
||||
*
|
||||
* @param[in] ec_context Pointer to EC context for signature generation.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] message_hash Pointer to octet message hash to be signed.
|
||||
* @param[in] hash_size Size of the message hash in bytes.
|
||||
* @param[out] signature Pointer to buffer to receive EC-DSA signature.
|
||||
* @param[in, out] sig_size On input, the size of signature buffer in bytes.
|
||||
* On output, the size of data returned in signature buffer in bytes.
|
||||
*
|
||||
* @retval true signature successfully generated in EC-DSA.
|
||||
* @retval false signature generation failed.
|
||||
* @retval false sig_size is too small.
|
||||
**/
|
||||
extern bool libspdm_ecdsa_sign(void *ec_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
uint8_t *signature, size_t *sig_size);
|
||||
|
||||
/**
|
||||
* Verifies the EC-DSA signature.
|
||||
*
|
||||
* If ec_context is NULL, then return false.
|
||||
* If message_hash is NULL, then return false.
|
||||
* If signature is NULL, then return false.
|
||||
* If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256,
|
||||
* SHA3_384, SHA3_512.
|
||||
*
|
||||
* For P-256, the sig_size is 64. first 32-byte is R, second 32-byte is S.
|
||||
* For P-384, the sig_size is 96. first 48-byte is R, second 48-byte is S.
|
||||
* For P-521, the sig_size is 132. first 66-byte is R, second 66-byte is S.
|
||||
*
|
||||
* @param[in] ec_context Pointer to EC context for signature verification.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] message_hash Pointer to octet message hash to be checked.
|
||||
* @param[in] hash_size Size of the message hash in bytes.
|
||||
* @param[in] signature Pointer to EC-DSA signature to be verified.
|
||||
* @param[in] sig_size Size of signature in bytes.
|
||||
*
|
||||
* @retval true Valid signature encoded in EC-DSA.
|
||||
* @retval false Invalid signature or invalid EC context.
|
||||
**/
|
||||
extern bool libspdm_ecdsa_verify(void *ec_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
const uint8_t *signature, size_t sig_size);
|
||||
#endif /* LIBSPDM_ECDSA_SUPPORT */
|
||||
#endif /* CRYPTLIB_EC_H */
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_ECD_H
|
||||
#define CRYPTLIB_ECD_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Edwards-Curve Primitives
|
||||
*=====================================================================================*/
|
||||
|
||||
#if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
|
||||
/**
|
||||
* Allocates and Initializes one Edwards-Curve context for subsequent use with the NID.
|
||||
*
|
||||
* @param nid cipher NID
|
||||
*
|
||||
* @return Pointer to the Edwards-Curve context that has been initialized.
|
||||
* If the allocations fails, libspdm_ecd_new_by_nid() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_ecd_new_by_nid(size_t nid);
|
||||
|
||||
/**
|
||||
* Release the specified Ed context.
|
||||
*
|
||||
* @param[in] ecd_context Pointer to the Ed context to be released.
|
||||
**/
|
||||
extern void libspdm_ecd_free(void *ecd_context);
|
||||
|
||||
/**
|
||||
* Carries out the Ed-DSA signature.
|
||||
*
|
||||
* This function carries out the Ed-DSA signature.
|
||||
* If the signature buffer is too small to hold the contents of signature, false
|
||||
* is returned and sig_size is set to the required buffer size to obtain the signature.
|
||||
*
|
||||
* If ecd_context is NULL, then return false.
|
||||
* If message is NULL, then return false.
|
||||
* hash_nid must be NULL.
|
||||
* If sig_size is large enough but signature is NULL, then return false.
|
||||
*
|
||||
* For ed25519, context must be NULL and context_size must be 0.
|
||||
* For ed448, context must be maximum of 255 octets.
|
||||
*
|
||||
* For ed25519, the sig_size is 64. first 32-byte is R, second 32-byte is S.
|
||||
* For ed448, the sig_size is 114. first 57-byte is R, second 57-byte is S.
|
||||
*
|
||||
* @param[in] ecd_context Pointer to Ed context for signature generation.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] context The EDDSA signing context.
|
||||
* @param[in] context_size Size of EDDSA signing context.
|
||||
* @param[in] message Pointer to octet message to be signed (before hash).
|
||||
* @param[in] size size of the message in bytes.
|
||||
* @param[out] signature Pointer to buffer to receive Ed-DSA signature.
|
||||
* @param[in, out] sig_size On input, the size of signature buffer in bytes.
|
||||
* On output, the size of data returned in signature buffer in bytes.
|
||||
*
|
||||
* @retval true signature successfully generated in Ed-DSA.
|
||||
* @retval false signature generation failed.
|
||||
* @retval false sig_size is too small.
|
||||
**/
|
||||
extern bool libspdm_eddsa_sign(const void *ecd_context, size_t hash_nid,
|
||||
const uint8_t *context, size_t context_size,
|
||||
const uint8_t *message, size_t size, uint8_t *signature,
|
||||
size_t *sig_size);
|
||||
|
||||
/**
|
||||
* Verifies the Ed-DSA signature.
|
||||
*
|
||||
* If ecd_context is NULL, then return false.
|
||||
* If message is NULL, then return false.
|
||||
* If signature is NULL, then return false.
|
||||
* hash_nid must be NULL.
|
||||
*
|
||||
* For ed25519, context must be NULL and context_size must be 0.
|
||||
* For ed448, context must be maximum of 255 octets.
|
||||
*
|
||||
* For ed25519, the sig_size is 64. first 32-byte is R, second 32-byte is S.
|
||||
* For ed448, the sig_size is 114. first 57-byte is R, second 57-byte is S.
|
||||
*
|
||||
* @param[in] ecd_context Pointer to Ed context for signature verification.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] context The EDDSA signing context.
|
||||
* @param[in] context_size Size of EDDSA signing context.
|
||||
* @param[in] message Pointer to octet message to be checked (before hash).
|
||||
* @param[in] size Size of the message in bytes.
|
||||
* @param[in] signature Pointer to Ed-DSA signature to be verified.
|
||||
* @param[in] sig_size Size of signature in bytes.
|
||||
*
|
||||
* @retval true Valid signature encoded in Ed-DSA.
|
||||
* @retval false Invalid signature or invalid Ed context.
|
||||
**/
|
||||
extern bool libspdm_eddsa_verify(const void *ecd_context, size_t hash_nid,
|
||||
const uint8_t *context, size_t context_size,
|
||||
const uint8_t *message, size_t size,
|
||||
const uint8_t *signature, size_t sig_size);
|
||||
#endif /* (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT) */
|
||||
#endif /* CRYPTLIB_ECD_H */
|
||||
+772
@@ -0,0 +1,772 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_HASH_H
|
||||
#define CRYPTLIB_HASH_H
|
||||
|
||||
/* SHA-256 digest size in bytes. */
|
||||
#define LIBSPDM_SHA256_DIGEST_SIZE 32
|
||||
|
||||
/* SHA-384 digest size in bytes. */
|
||||
#define LIBSPDM_SHA384_DIGEST_SIZE 48
|
||||
|
||||
/* SHA-512 digest size in bytes. */
|
||||
#define LIBSPDM_SHA512_DIGEST_SIZE 64
|
||||
|
||||
/* SHA3-256 digest size in bytes. */
|
||||
#define LIBSPDM_SHA3_256_DIGEST_SIZE 32
|
||||
|
||||
/* SHA3-384 digest size in bytes. */
|
||||
#define LIBSPDM_SHA3_384_DIGEST_SIZE 48
|
||||
|
||||
/* SHA3-512 digest size in bytes. */
|
||||
#define LIBSPDM_SHA3_512_DIGEST_SIZE 64
|
||||
|
||||
/* SM3_256 digest size in bytes. */
|
||||
#define LIBSPDM_SM3_256_DIGEST_SIZE 32
|
||||
|
||||
/*=====================================================================================
|
||||
* One-way cryptographic hash SHA2 primitives.
|
||||
*=====================================================================================
|
||||
*/
|
||||
#if LIBSPDM_SHA256_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SHA-256 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, sha256_new() returns NULL. *
|
||||
**/
|
||||
extern void *libspdm_sha256_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sha256_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sha256_free(void *sha256_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed to by sha256_context as SHA-256 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sha256_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sha256_context Pointer to SHA-256 context being initialized.
|
||||
*
|
||||
* @retval true SHA-256 context initialization succeeded.
|
||||
* @retval false SHA-256 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sha256_init(void *sha256_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SHA-256 context.
|
||||
*
|
||||
* If sha256_context is NULL, then return false.
|
||||
* If new_sha256_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sha256_context Pointer to SHA-256 context being copied.
|
||||
* @param[out] new_sha256_context Pointer to new SHA-256 context.
|
||||
*
|
||||
* @retval true SHA-256 context copy succeeded.
|
||||
* @retval false SHA-256 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha256_duplicate(const void *sha256_context, void *new_sha256_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SHA-256 context.
|
||||
*
|
||||
* This function performs SHA-256 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SHA-256 context should be already correctly initialized by libspdm_sha256_init(), and must not
|
||||
* have been finalized by libspdm_sha256_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sha256_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha256_context Pointer to the SHA-256 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SHA-256 data digest succeeded.
|
||||
* @retval false SHA-256 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sha256_update(void *sha256_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SHA-256 digest value.
|
||||
*
|
||||
* This function completes SHA-256 hash computation and populates the digest value into
|
||||
* the specified memory. After this function has been called, the SHA-256 context cannot
|
||||
* be used again. SHA-256 context should be already correctly initialized by libspdm_sha256_init(),
|
||||
* and must not have been finalized by libspdm_sha256_final(). Behavior with invalid SHA-256 context
|
||||
* is undefined.
|
||||
*
|
||||
* If sha256_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha256_context Pointer to the SHA-256 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA-256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true SHA-256 digest computation succeeded.
|
||||
* @retval false SHA-256 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_sha256_final(void *sha256_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SHA-256 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SHA-256 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA-256 digest value (32 bytes).
|
||||
*
|
||||
* @retval true SHA-256 digest computation succeeded.
|
||||
* @retval false SHA-256 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha256_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SHA256_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA384_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SHA-384 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_sha384_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sha384_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sha384_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sha384_free(void *sha384_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed to by sha384_context as SHA-384 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sha384_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sha384_context Pointer to SHA-384 context being initialized.
|
||||
*
|
||||
* @retval true SHA-384 context initialization succeeded.
|
||||
* @retval false SHA-384 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sha384_init(void *sha384_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SHA-384 context.
|
||||
*
|
||||
* If sha384_context is NULL, then return false.
|
||||
* If new_sha384_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sha384_context Pointer to SHA-384 context being copied.
|
||||
* @param[out] new_sha384_context Pointer to new SHA-384 context.
|
||||
*
|
||||
* @retval true SHA-384 context copy succeeded.
|
||||
* @retval false SHA-384 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha384_duplicate(const void *sha384_context, void *new_sha384_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SHA-384 context.
|
||||
*
|
||||
* This function performs SHA-384 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SHA-384 context should be already correctly initialized by libspdm_sha384_init(), and must not
|
||||
* have been finalized by libspdm_sha384_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sha384_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha384_context Pointer to the SHA-384 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SHA-384 data digest succeeded.
|
||||
* @retval false SHA-384 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sha384_update(void *sha384_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SHA-384 digest value.
|
||||
*
|
||||
* This function completes SHA-384 hash computation and populates the digest value into
|
||||
* the specified memory. After this function has been called, the SHA-384 context cannot
|
||||
* be used again. SHA-384 context should be already correctly initialized by libspdm_sha384_init(),
|
||||
* and must not have been finalized by libspdm_sha384_final(). Behavior with invalid SHA-384 context
|
||||
* is undefined.
|
||||
*
|
||||
* If sha384_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha384_context Pointer to the SHA-384 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA-384 digest
|
||||
* value (48 bytes).
|
||||
*
|
||||
* @retval true SHA-384 digest computation succeeded.
|
||||
* @retval false SHA-384 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_sha384_final(void *sha384_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SHA-384 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SHA-384 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA-384 digest value (48 bytes).
|
||||
*
|
||||
* @retval true SHA-384 digest computation succeeded.
|
||||
* @retval false SHA-384 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha384_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SHA384_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA512_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SHA-512 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_sha512_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sha512_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sha512_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sha512_free(void *sha512_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed by sha512_context as SHA-512 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sha512_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sha512_context Pointer to SHA-512 context being initialized.
|
||||
*
|
||||
* @retval true SHA-512 context initialization succeeded.
|
||||
* @retval false SHA-512 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sha512_init(void *sha512_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SHA-512 context.
|
||||
*
|
||||
* If sha512_context is NULL, then return false.
|
||||
* If new_sha512_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sha512_context Pointer to SHA-512 context being copied.
|
||||
* @param[out] new_sha512_context Pointer to new SHA-512 context.
|
||||
*
|
||||
* @retval true SHA-512 context copy succeeded.
|
||||
* @retval false SHA-512 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha512_duplicate(const void *sha512_context, void *new_sha512_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SHA-512 context.
|
||||
*
|
||||
* This function performs SHA-512 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SHA-512 context should be already correctly initialized by libspdm_sha512_init(), and must not
|
||||
* have been finalized by libspdm_sha512_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sha512_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha512_context Pointer to the SHA-512 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SHA-512 data digest succeeded.
|
||||
* @retval false SHA-512 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sha512_update(void *sha512_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SHA-512 digest value.
|
||||
*
|
||||
* This function completes SHA-512 hash computation and populates the digest value into
|
||||
* the specified memory. After this function has been called, the SHA-512 context cannot
|
||||
* be used again. SHA-512 context should be already correctly initialized by libspdm_sha512_init(),
|
||||
* and must not have been finalized by libspdm_sha512_final(). Behavior with invalid SHA-512 context
|
||||
* is undefined.
|
||||
*
|
||||
* If sha512_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha512_context Pointer to the SHA-512 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA-512 digest
|
||||
* value (64 bytes).
|
||||
*
|
||||
* @retval true SHA-512 digest computation succeeded.
|
||||
* @retval false SHA-512 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_sha512_final(void *sha512_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SHA-512 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SHA-512 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA-512 digest value (64 bytes).
|
||||
*
|
||||
* @retval true SHA-512 digest computation succeeded.
|
||||
* @retval false SHA-512 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha512_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SHA512_SUPPORT */
|
||||
|
||||
/*=====================================================================================
|
||||
* One-way cryptographic hash SHA3 primitives.
|
||||
*=====================================================================================
|
||||
*/
|
||||
#if LIBSPDM_SHA3_256_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SHA3-256 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_sha3_256_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sha3_256_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sha3_256_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sha3_256_free(void *sha3_256_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed by sha3_256_context as SHA3-256 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sha3_256_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sha3_256_context Pointer to SHA3-256 context being initialized.
|
||||
*
|
||||
* @retval true SHA3-256 context initialization succeeded.
|
||||
* @retval false SHA3-256 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_256_init(void *sha3_256_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SHA3-256 context.
|
||||
*
|
||||
* If sha3_256_context is NULL, then return false.
|
||||
* If new_sha3_256_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sha3_256_context Pointer to SHA3-256 context being copied.
|
||||
* @param[out] new_sha3_256_context Pointer to new SHA3-256 context.
|
||||
*
|
||||
* @retval true SHA3-256 context copy succeeded.
|
||||
* @retval false SHA3-256 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha3_256_duplicate(const void *sha3_256_context, void *new_sha3_256_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SHA3-256 context.
|
||||
*
|
||||
* This function performs SHA3-256 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SHA3-256 context should be already correctly initialized by libspdm_sha3_256_init(), and must not
|
||||
* have been finalized by libspdm_sha3_256_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sha3_256_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha3_256_context Pointer to the SHA3-256 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SHA3-256 data digest succeeded.
|
||||
* @retval false SHA3-256 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_256_update(void *sha3_256_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SHA3-256 digest value.
|
||||
*
|
||||
* This function completes SHA3-256 hash computation and populates the digest value into
|
||||
* the specified memory. After this function has been called, the SHA3-512 context cannot
|
||||
* be used again. SHA3-256 context should be already correctly initialized by
|
||||
* libspdm_sha3_256_init(), and must not have been finalized by libspdm_sha3_256_final().
|
||||
* Behavior with invalid SHA3-256 context is undefined.
|
||||
*
|
||||
* If sha3_256_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha3_256_context Pointer to the SHA3-256 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA3-256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true SHA3-256 digest computation succeeded.
|
||||
* @retval false SHA3-256 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_256_final(void *sha3_256_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SHA3-256 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SHA3-256 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA3-256 digest value (32 bytes).
|
||||
*
|
||||
* @retval true SHA3-256 digest computation succeeded.
|
||||
* @retval false SHA3-256 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha3_256_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SHA3_256_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_384_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SHA3-384 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_sha3_384_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sha3_384_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sha3_384_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sha3_384_free(void *sha3_384_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed by sha3_384_context as SHA3-384 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sha3_384_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sha3_384_context Pointer to SHA3-384 context being initialized.
|
||||
*
|
||||
* @retval true SHA3-384 context initialization succeeded.
|
||||
* @retval false SHA3-384 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_384_init(void *sha3_384_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SHA3-384 context.
|
||||
*
|
||||
* If sha3_384_context is NULL, then return false.
|
||||
* If new_sha3_384_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sha3_384_context Pointer to SHA3-384 context being copied.
|
||||
* @param[out] new_sha3_384_context Pointer to new SHA3-384 context.
|
||||
*
|
||||
* @retval true SHA3-384 context copy succeeded.
|
||||
* @retval false SHA3-384 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha3_384_duplicate(const void *sha3_384_context, void *new_sha3_384_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SHA3-384 context.
|
||||
*
|
||||
* This function performs SHA3-384 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SHA3-384 context should be already correctly initialized by libspdm_sha3_384_init(), and must not
|
||||
* have been finalized by libspdm_sha3_384_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sha3_384_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha3_384_context Pointer to the SHA3-384 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SHA3-384 data digest succeeded.
|
||||
* @retval false SHA3-384 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_384_update(void *sha3_384_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SHA3-384 digest value.
|
||||
*
|
||||
* This function completes SHA3-384 hash computation and populates the digest value into
|
||||
* the specified memory. After this function has been called, the SHA3-384 context cannot
|
||||
* be used again. SHA3-384 context should be already correctly initialized by
|
||||
* libspdm_sha3_384_init(), and must not have been finalized by libspdm_sha3_384_final().
|
||||
* Behavior with invalid SHA3-384 context is undefined.
|
||||
*
|
||||
* If sha3_384_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha3_384_context Pointer to the SHA3-384 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA3-384 digest
|
||||
* value (48 bytes).
|
||||
*
|
||||
* @retval true SHA3-384 digest computation succeeded.
|
||||
* @retval false SHA3-384 digest computation failed.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_sha3_384_final(void *sha3_384_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SHA3-384 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SHA3-384 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA3-384 digest value (48 bytes).
|
||||
*
|
||||
* @retval true SHA3-384 digest computation succeeded.
|
||||
* @retval false SHA3-384 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha3_384_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SHA3_384_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_512_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SHA3-512 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_sha3_512_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sha3_512_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sha3_512_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sha3_512_free(void *sha3_512_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed by sha3_512_context as SHA3-512 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sha3_512_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sha3_512_context Pointer to SHA3-512 context being initialized.
|
||||
*
|
||||
* @retval true SHA3-512 context initialization succeeded.
|
||||
* @retval false SHA3-512 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_512_init(void *sha3_512_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SHA3-512 context.
|
||||
*
|
||||
* If sha3_512_context is NULL, then return false.
|
||||
* If new_sha3_512_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sha3_512_context Pointer to SHA3-512 context being copied.
|
||||
* @param[out] new_sha3_512_context Pointer to new SHA3-512 context.
|
||||
*
|
||||
* @retval true SHA3-512 context copy succeeded.
|
||||
* @retval false SHA3-512 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_sha3_512_duplicate(const void *sha3_512_context, void *new_sha3_512_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SHA3-512 context.
|
||||
*
|
||||
* This function performs SHA3-512 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SHA3-512 context should be already correctly initialized by libspdm_sha3_512_init(), and must not
|
||||
* have been finalized by libspdm_sha3_512_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sha3_512_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha3_512_context Pointer to the SHA3-512 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SHA3-512 data digest succeeded.
|
||||
* @retval false SHA3-512 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_512_update(void *sha3_512_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SHA3-512 digest value.
|
||||
*
|
||||
* This function completes SHA3-512 hash computation and populates the digest value into
|
||||
* the specified memory. After this function has been called, the SHA3-512 context cannot
|
||||
* be used again. SHA3-512 context should be already correctly initialized by
|
||||
* libspdm_sha3_512_init(), and must not have been finalized by libspdm_sha3_512_final().
|
||||
* Behavior with invalid SHA3-512 context is undefined.
|
||||
*
|
||||
* If sha3_512_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sha3_512_context Pointer to the SHA3-512 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA3-512 digest
|
||||
* value (64 bytes).
|
||||
*
|
||||
* @retval true SHA3-512 digest computation succeeded.
|
||||
* @retval false SHA3-512 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_sha3_512_final(void *sha3_512_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SHA3-512 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SHA3-512 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SHA3-512 digest value (64 bytes).
|
||||
*
|
||||
* @retval true SHA3-512 digest computation succeeded.
|
||||
* @retval false SHA3-512 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sha3_512_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SHA3_512_SUPPORT */
|
||||
|
||||
/*=====================================================================================
|
||||
* One-Way Cryptographic hash SM3 Primitives
|
||||
*=====================================================================================
|
||||
*/
|
||||
|
||||
#if LIBSPDM_SM3_256_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HASH_CTX context for subsequent SM3-256 use.
|
||||
*
|
||||
* @return Pointer to the HASH_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_sm3_256_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sm3_256_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HASH_CTX context.
|
||||
*
|
||||
* @param[in] sm3_context Pointer to the HASH_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_sm3_256_free(void *sm3_context);
|
||||
|
||||
/**
|
||||
* Initializes user-supplied memory pointed by sm3_context as SM3 hash context for
|
||||
* subsequent use.
|
||||
*
|
||||
* If sm3_context is NULL, then return false.
|
||||
*
|
||||
* @param[out] sm3_context Pointer to SM3 context being initialized.
|
||||
*
|
||||
* @retval true SM3 context initialization succeeded.
|
||||
* @retval false SM3 context initialization failed.
|
||||
**/
|
||||
extern bool libspdm_sm3_256_init(void *sm3_context);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing SM3 context.
|
||||
*
|
||||
* If sm3_context is NULL, then return false.
|
||||
* If new_sm3_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] sm3_context Pointer to SM3 context being copied.
|
||||
* @param[out] new_sm3_context Pointer to new SM3 context.
|
||||
*
|
||||
* @retval true SM3 context copy succeeded.
|
||||
* @retval false SM3 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sm3_256_duplicate(const void *sm3_context, void *new_sm3_context);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates SM3 context.
|
||||
*
|
||||
* This function performs SM3 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* SM3 context should be already correctly initialized by sm3_init(), and should not be finalized
|
||||
* by sm3_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If sm3_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sm3_context Pointer to the SM3 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true SM3 data digest succeeded.
|
||||
* @retval false SM3 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_sm3_256_update(void *sm3_context, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the SM3 digest value.
|
||||
*
|
||||
* This function completes SM3 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the SM3 context cannot
|
||||
* be used again. SM3 context should be already correctly initialized by sm3_init(), and should not
|
||||
* be finalized by sm3_final(). Behavior with invalid SM3 context is undefined.
|
||||
*
|
||||
* If sm3_context is NULL, then return false.
|
||||
* If hash_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sm3_context Pointer to the SM3 context.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SM3 digest value (32 bytes).
|
||||
*
|
||||
* @retval true SM3 digest computation succeeded.
|
||||
* @retval false SM3 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_sm3_256_final(void *sm3_context, uint8_t *hash_value);
|
||||
|
||||
/**
|
||||
* Computes the SM3 message digest of an input data buffer.
|
||||
*
|
||||
* This function performs the SM3 message digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be hashed.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[out] hash_value Pointer to a buffer that receives the SM3 digest value (32 bytes).
|
||||
*
|
||||
* @retval true SM3 digest computation succeeded.
|
||||
* @retval false SM3 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_sm3_256_hash_all(const void *data, size_t data_size, uint8_t *hash_value);
|
||||
#endif /* LIBSPDM_SM3_256_SUPPORT */
|
||||
|
||||
#endif /* CRYPTLIB_HASH_H */
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_HKDF_H
|
||||
#define CRYPTLIB_HKDF_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Key Derivation Function Primitives
|
||||
*=====================================================================================*/
|
||||
|
||||
#if LIBSPDM_SHA256_SUPPORT
|
||||
/**
|
||||
* Derive SHA-256 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive prk value.
|
||||
* @param[in] prk_out_size Size of prk bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha256_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SHA256 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha256_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SHA256_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA384_SUPPORT
|
||||
/**
|
||||
* Derive SHA384 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] prk_out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha384_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SHA384 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha384_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SHA384_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA512_SUPPORT
|
||||
/**
|
||||
* Derive SHA512 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] prk_out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha512_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SHA512 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha512_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SHA512_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_256_SUPPORT
|
||||
/**
|
||||
* Derive SHA3_256 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] prk_out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha3_256_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SHA3_256 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha3_256_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SHA3_256_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_384_SUPPORT
|
||||
/**
|
||||
* Derive SHA3_384 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] prk_out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha3_384_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SHA3_384 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha3_384_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SHA3_384_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_512_SUPPORT
|
||||
/**
|
||||
* Derive SHA3_512 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] prk_out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha3_512_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SHA3_512 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sha3_512_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SHA3_512_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SM3_256_SUPPORT
|
||||
/**
|
||||
* Derive SM3_256 HMAC-based Extract key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[in] salt Pointer to the salt value.
|
||||
* @param[in] salt_size Salt size in bytes.
|
||||
* @param[out] prk_out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] prk_out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sm3_256_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size);
|
||||
|
||||
/**
|
||||
* Derive SM3_256 HMAC-based Expand key Derivation Function (HKDF).
|
||||
*
|
||||
* @param[in] prk Pointer to the user-supplied key.
|
||||
* @param[in] prk_size Key size in bytes.
|
||||
* @param[in] info Pointer to the application specific info.
|
||||
* @param[in] info_size Info size in bytes.
|
||||
* @param[out] out Pointer to buffer to receive hkdf value.
|
||||
* @param[in] out_size Size of hkdf bytes to generate.
|
||||
*
|
||||
* @retval true Hkdf generated successfully.
|
||||
* @retval false Hkdf generation failed.
|
||||
**/
|
||||
extern bool libspdm_hkdf_sm3_256_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
#endif /* LIBSPDM_SM3_256_SUPPORT */
|
||||
|
||||
#endif /* CRYPTLIB_HKDF_H */
|
||||
+833
@@ -0,0 +1,833 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_MAC_H
|
||||
#define CRYPTLIB_MAC_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Message Authentication Code (MAC) Primitives
|
||||
*=====================================================================================
|
||||
*/
|
||||
|
||||
#if LIBSPDM_SHA256_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA256 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sha256_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sha256_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sha256_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sha256_free(void *hmac_sha256_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sha256_update().
|
||||
*
|
||||
* If hmac_sha256_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[out] hmac_sha256_ctx Pointer to HMAC-SHA256 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha256_set_key(void *hmac_sha256_ctx, const uint8_t *key, size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SHA256 context.
|
||||
*
|
||||
* If hmac_sha256_ctx is NULL, then return false.
|
||||
* If new_hmac_sha256_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] hmac_sha256_ctx Pointer to HMAC-SHA256 context being copied.
|
||||
* @param[out] new_hmac_sha256_ctx Pointer to new HMAC-SHA256 context.
|
||||
*
|
||||
* @retval true HMAC-SHA256 context copy succeeded.
|
||||
* @retval false HMAC-SHA256 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha256_duplicate(const void *hmac_sha256_ctx, void *new_hmac_sha256_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SHA256 context.
|
||||
*
|
||||
* This function performs HMAC-SHA256 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SHA256 context should be initialized by libspdm_hmac_sha256_new(), and should not be
|
||||
* finalized by libspdm_hmac_sha256_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sha256_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha256_ctx Pointer to the HMAC-SHA256 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SHA256 data digest succeeded.
|
||||
* @retval false HMAC-SHA256 data digest failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha256_update(void *hmac_sha256_ctx, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SHA256 digest value.
|
||||
*
|
||||
* This function completes HMAC-SHA256 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SHA256 context cannot
|
||||
* be used again. HMAC-SHA256 context should be initialized by libspdm_hmac_sha256_new(), and should
|
||||
* not be finalized by libspdm_hmac_sha256_final(). Behavior with invalid HMAC-SHA256 context is
|
||||
* undefined.
|
||||
*
|
||||
* If hmac_sha256_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha256_ctx Pointer to the HMAC-SHA256 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA256 digest computation succeeded.
|
||||
* @retval false HMAC-SHA256 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha256_final(void *hmac_sha256_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SHA256 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SHA256 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA256 digest computation succeeded.
|
||||
* @retval false HMAC-SHA256 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha256_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SHA256_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA384_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA384 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sha384_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sha384_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sha384_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sha384_free(void *hmac_sha384_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sha384_update().
|
||||
*
|
||||
* If hmac_sha384_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[out] hmac_sha384_ctx Pointer to HMAC-SHA384 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha384_set_key(void *hmac_sha384_ctx, const uint8_t *key, size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SHA384 context.
|
||||
*
|
||||
* If hmac_sha384_ctx is NULL, then return false.
|
||||
* If new_hmac_sha384_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] hmac_sha384_ctx Pointer to HMAC-SHA384 context being copied.
|
||||
* @param[out] new_hmac_sha384_ctx Pointer to new HMAC-SHA384 context.
|
||||
*
|
||||
* @retval true HMAC-SHA384 context copy succeeded.
|
||||
* @retval false HMAC-SHA384 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha384_duplicate(const void *hmac_sha384_ctx, void *new_hmac_sha384_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SHA384 context.
|
||||
*
|
||||
* This function performs HMAC-SHA384 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SHA384 context should be initialized by libspdm_hmac_sha384_new(), and should not be
|
||||
* finalized by libspdm_hmac_sha384_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sha384_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha384_ctx Pointer to the HMAC-SHA384 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SHA384 data digest succeeded.
|
||||
* @retval false HMAC-SHA384 data digest failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha384_update(void *hmac_sha384_ctx, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SHA384 digest value.
|
||||
*
|
||||
* This function completes HMAC-SHA384 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SHA384 context cannot
|
||||
* be used again. HMAC-SHA384 context should be initialized by libspdm_hmac_sha384_new(), and should
|
||||
* not be finalized by libspdm_hmac_sha384_final(). Behavior with invalid HMAC-SHA384 context is
|
||||
* undefined.
|
||||
*
|
||||
* If hmac_sha384_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha384_ctx Pointer to the HMAC-SHA384 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA384 digest
|
||||
* value (48 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA384 digest computation succeeded.
|
||||
* @retval false HMAC-SHA384 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha384_final(void *hmac_sha384_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SHA384 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SHA384 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA384 digest
|
||||
* value (48 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA384 digest computation succeeded.
|
||||
* @retval false HMAC-SHA384 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha384_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SHA384_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA512_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA512 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sha512_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sha512_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sha512_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sha512_free(void *hmac_sha512_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sha512_update().
|
||||
*
|
||||
* If hmac_sha512_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[out] hmac_sha512_ctx Pointer to HMAC-SHA512 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha512_set_key(void *hmac_sha512_ctx, const uint8_t *key, size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SHA512 context.
|
||||
*
|
||||
* If hmac_sha512_ctx is NULL, then return false.
|
||||
* If new_hmac_sha512_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] hmac_sha512_ctx Pointer to HMAC-SHA512 context being copied.
|
||||
* @param[out] new_hmac_sha512_ctx Pointer to new HMAC-SHA512 context.
|
||||
*
|
||||
* @retval true HMAC-SHA512 context copy succeeded.
|
||||
* @retval false HMAC-SHA512 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha512_duplicate(const void *hmac_sha512_ctx, void *new_hmac_sha512_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SHA512 context.
|
||||
*
|
||||
* This function performs HMAC-SHA512 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SHA512 context should be initialized by libspdm_hmac_sha512_new(), and should not be
|
||||
* finalized by libspdm_hmac_sha512_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sha512_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha512_ctx Pointer to the HMAC-SHA512 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SHA512 data digest succeeded.
|
||||
* @retval false HMAC-SHA512 data digest failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha512_update(void *hmac_sha512_ctx, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SHA512 digest value.
|
||||
*
|
||||
* This function completes HMAC-SHA512 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SHA512 context cannot
|
||||
* be used again. HMAC-SHA512 context should be initialized by libspdm_hmac_sha512_new(), and should
|
||||
* not be finalized by libspdm_hmac_sha512_final(). Behavior with invalid HMAC-SHA512 context is
|
||||
* undefined.
|
||||
*
|
||||
* If hmac_sha512_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha512_ctx Pointer to the HMAC-SHA512 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA512 digest
|
||||
* value (64 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA512 digest computation succeeded.
|
||||
* @retval false HMAC-SHA512 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha512_final(void *hmac_sha512_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SHA512 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SHA512 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA512 digest
|
||||
* value (64 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA512 digest computation succeeded.
|
||||
* @retval false HMAC-SHA512 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_hmac_sha512_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SHA512_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_256_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA3-256 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sha3_256_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sha3_256_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sha3_256_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sha3_256_free(void *hmac_sha3_256_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sha3_256_update().
|
||||
*
|
||||
* If hmac_sha3_256_ctx is NULL, then return false.
|
||||
*
|
||||
* @param[out] hmac_sha3_256_ctx Pointer to HMAC-SHA3-256 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_256_set_key(void *hmac_sha3_256_ctx,
|
||||
const uint8_t *key,
|
||||
size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SHA3-256 context.
|
||||
*
|
||||
* If hmac_sha3_256_ctx is NULL, then return false.
|
||||
* If new_hmac_sha3_256_ctx is NULL, then return false.
|
||||
*
|
||||
* @param[in] hmac_sha3_256_ctx Pointer to HMAC-SHA3-256 context being copied.
|
||||
* @param[out] new_hmac_sha3_256_ctx Pointer to new HMAC-SHA3-256 context.
|
||||
*
|
||||
* @retval true HMAC-SHA3-256 context copy succeeded.
|
||||
* @retval false HMAC-SHA3-256 context copy failed.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_256_duplicate(const void *hmac_sha3_256_ctx,
|
||||
void *new_hmac_sha3_256_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SHA3-256 context.
|
||||
*
|
||||
* This function performs HMAC-SHA3-256 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SHA3-256 context should be initialized by libspdm_hmac_sha3_256_new(), and should not be
|
||||
* finalized by libspdm_hmac_sha3_256_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sha3_256_ctx is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha3_256_ctx Pointer to the HMAC-SHA3-256 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SHA3-256 data digest succeeded.
|
||||
* @retval false HMAC-SHA3-256 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_256_update(void *hmac_sha3_256_ctx,
|
||||
const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SHA3-256 digest value.
|
||||
*
|
||||
* This function completes HMAC-SHA3-256 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SHA3-256 context cannot
|
||||
* be used again. HMAC-SHA3-256 context should be initialized by libspdm_hmac_sha3_256_new(), and
|
||||
* should not be finalized by libspdm_hmac_sha3_256_final(). Behavior with invalid HMAC-SHA3-256
|
||||
* context is undefined.
|
||||
*
|
||||
* If hmac_sha3_256_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha3_256_ctx Pointer to the HMAC-SHA3-256 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA3-256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA3-256 digest computation succeeded.
|
||||
* @retval false HMAC-SHA3-256 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_256_final(void *hmac_sha3_256_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SHA3-256 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SHA3-256 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA3-256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA3-256 digest computation succeeded.
|
||||
* @retval false HMAC-SHA3-256 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_256_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SHA3_256_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_384_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA3-384 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sha3_384_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sha3_384_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sha3_384_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sha3_384_free(void *hmac_sha3_384_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sha3_384_update().
|
||||
*
|
||||
* If hmac_sha3_384_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[out] hmac_sha3_384_ctx Pointer to HMAC-SHA3-384 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_384_set_key(void *hmac_sha3_384_ctx,
|
||||
const uint8_t *key,
|
||||
size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SHA3-384 context.
|
||||
*
|
||||
* If hmac_sha3_384_ctx is NULL, then return false.
|
||||
* If new_hmac_sha3_384_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] hmac_sha3_384_ctx Pointer to HMAC-SHA3-384 context being copied.
|
||||
* @param[out] new_hmac_sha3_384_ctx Pointer to new HMAC-SHA3-384 context.
|
||||
*
|
||||
* @retval true HMAC-SHA3-384 context copy succeeded.
|
||||
* @retval false HMAC-SHA3-384 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_384_duplicate(const void *hmac_sha3_384_ctx,
|
||||
void *new_hmac_sha3_384_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SHA3-384 context.
|
||||
*
|
||||
* This function performs HMAC-SHA3-384 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SHA3-384 context should be initialized by libspdm_hmac_sha3_384_new(), and should not be
|
||||
* finalized by libspdm_hmac_sha3_384_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sha3_384_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha3_384_ctx Pointer to the HMAC-SHA3-384 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SHA3-384 data digest succeeded.
|
||||
* @retval false HMAC-SHA3-384 data digest failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_384_update(void *hmac_sha3_384_ctx, const void *data,
|
||||
size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SHA3-384 digest value.
|
||||
*
|
||||
* This function completes HMAC-SHA3-384 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SHA3-384 context cannot
|
||||
* be used again. HMAC-SHA3-384 context should be initialized by libspdm_hmac_sha3_384_new(), and
|
||||
* should not be finalized by libspdm_hmac_sha3_384_final(). Behavior with invalid HMAC-SHA3-384
|
||||
* context is undefined.
|
||||
*
|
||||
* If hmac_sha3_384_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha3_384_ctx Pointer to the HMAC-SHA3-384 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA3-384 digest
|
||||
* value (48 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA3-384 digest computation succeeded.
|
||||
* @retval false HMAC-SHA3-384 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_384_final(void *hmac_sha3_384_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SHA3-384 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SHA3-384 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA3-384 digest
|
||||
* value (48 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA3-384 digest computation succeeded.
|
||||
* @retval false HMAC-SHA3-384 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_384_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SHA3_384_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SHA3_512_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA3-512 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sha3_512_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sha3_512_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sha3_512_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sha3_512_free(void *hmac_sha3_512_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sha3_512_update().
|
||||
*
|
||||
* If hmac_sha3_512_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[out] hmac_sha3_512_ctx Pointer to HMAC-SHA3-512 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_512_set_key(void *hmac_sha3_512_ctx,
|
||||
const uint8_t *key,
|
||||
size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SHA3-512 context.
|
||||
*
|
||||
* If hmac_sha3_512_ctx is NULL, then return false.
|
||||
* If new_hmac_sha3_512_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] hmac_sha3_512_ctx Pointer to HMAC-SHA3-512 context being copied.
|
||||
* @param[out] new_hmac_sha3_512_ctx Pointer to new HMAC-SHA3-512 context.
|
||||
*
|
||||
* @retval true HMAC-SHA3-512 context copy succeeded.
|
||||
* @retval false HMAC-SHA3-512 context copy failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_512_duplicate(const void *hmac_sha3_512_ctx,
|
||||
void *new_hmac_sha3_512_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SHA3-512 context.
|
||||
*
|
||||
* This function performs HMAC-SHA3-512 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SHA3-512 context should be initialized by libspdm_hmac_sha3_512_new(), and should not be
|
||||
* finalized by libspdm_hmac_sha3_512_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sha3_512_ctx is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha3_512_ctx Pointer to the HMAC-SHA3-512 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SHA3-512 data digest succeeded.
|
||||
* @retval false HMAC-SHA3-512 data digest failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_512_update(void *hmac_sha3_512_ctx,
|
||||
const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SHA3-512 digest value.
|
||||
*
|
||||
* This function completes HMAC-SHA3-512 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SHA3-512 context cannot
|
||||
* be used again. HMAC-SHA3-512 context should be initialized by libspdm_hmac_sha3_512_new(), and
|
||||
* should not be finalized by libspdm_hmac_sha3_512_final(). Behavior with invalid HMAC-SHA3-512
|
||||
* context is undefined.
|
||||
*
|
||||
* If hmac_sha3_512_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sha3_512_ctx Pointer to the HMAC-SHA3-512 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA3-512 digest
|
||||
* value (64 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA3-512 digest computation succeeded.
|
||||
* @retval false HMAC-SHA3-512 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_512_final(void *hmac_sha3_512_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SHA3-512 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SHA3-512 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SHA3-512 digest
|
||||
* value (64 bytes).
|
||||
*
|
||||
* @retval true HMAC-SHA3-512 digest computation succeeded.
|
||||
* @retval false HMAC-SHA3-512 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sha3_512_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SHA3_512_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SM3_256_SUPPORT
|
||||
/**
|
||||
* Allocates and initializes one HMAC_CTX context for subsequent HMAC-SM3-256 use.
|
||||
*
|
||||
* @return Pointer to the HMAC_CTX context that has been initialized.
|
||||
* If the allocations fails, libspdm_hmac_sm3_256_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_hmac_sm3_256_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified HMAC_CTX context.
|
||||
*
|
||||
* @param[in] hmac_sm3_256_ctx Pointer to the HMAC_CTX context to be released.
|
||||
**/
|
||||
extern void libspdm_hmac_sm3_256_free(void *hmac_sm3_256_ctx);
|
||||
|
||||
/**
|
||||
* Set user-supplied key for subsequent use. It must be done before any
|
||||
* calling to libspdm_hmac_sm3_256_update().
|
||||
*
|
||||
* If hmac_sm3_256_ctx is NULL, then return false.
|
||||
*
|
||||
* @param[out] hmac_sm3_256_ctx Pointer to HMAC-SM3-256 context.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
*
|
||||
* @retval true The key is set successfully.
|
||||
* @retval false The key is set unsuccessfully.
|
||||
**/
|
||||
extern bool libspdm_hmac_sm3_256_set_key(void *hmac_sm3_256_ctx,
|
||||
const uint8_t *key, size_t key_size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing HMAC-SM3-256 context.
|
||||
*
|
||||
* If hmac_sm3_256_ctx is NULL, then return false.
|
||||
* If new_hmac_sm3_256_ctx is NULL, then return false.
|
||||
*
|
||||
* @param[in] hmac_sm3_256_ctx Pointer to HMAC-SM3-256 context being copied.
|
||||
* @param[out] new_hmac_sm3_256_ctx Pointer to new HMAC-SM3-256 context.
|
||||
*
|
||||
* @retval true HMAC-SM3-256 context copy succeeded.
|
||||
* @retval false HMAC-SM3-256 context copy failed.
|
||||
**/
|
||||
extern bool libspdm_hmac_sm3_256_duplicate(const void *hmac_sm3_256_ctx,
|
||||
void *new_hmac_sm3_256_ctx);
|
||||
|
||||
/**
|
||||
* Digests the input data and updates HMAC-SM3-256 context.
|
||||
*
|
||||
* This function performs HMAC-SM3-256 digest on a data buffer of the specified size.
|
||||
* It can be called multiple times to compute the digest of long or discontinuous data streams.
|
||||
* HMAC-SM3-256 context should be initialized by libspdm_hmac_sm3_256_new(), and should not be
|
||||
* finalized by libspdm_hmac_sm3_256_final(). Behavior with invalid context is undefined.
|
||||
*
|
||||
* If hmac_sm3_256_ctx is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sm3_256_ctx Pointer to the HMAC-SM3-256 context.
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
*
|
||||
* @retval true HMAC-SM3-256 data digest succeeded.
|
||||
* @retval false HMAC-SM3-256 data digest failed.
|
||||
**/
|
||||
extern bool libspdm_hmac_sm3_256_update(void *hmac_sm3_256_ctx, const void *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Completes computation of the HMAC-SM3-256 digest value.
|
||||
*
|
||||
* This function completes HMAC-SM3-256 hash computation and retrieves the digest value into
|
||||
* the specified memory. After this function has been called, the HMAC-SM3-256 context cannot
|
||||
* be used again. HMAC-SM3-256 context should be initialized by libspdm_hmac_sm3_256_new(), and
|
||||
* should not be finalized by libspdm_hmac_sm3_256_final(). Behavior with invalid HMAC-SM3-256
|
||||
* context is undefined.
|
||||
*
|
||||
* If hmac_sm3_256_ctx is NULL, then return false.
|
||||
* If hmac_value is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] hmac_sm3_256_ctx Pointer to the HMAC-SM3-256 context.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SM3-256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true HMAC-SM3-256 digest computation succeeded.
|
||||
* @retval false HMAC-SM3-256 digest computation failed.
|
||||
**/
|
||||
extern bool libspdm_hmac_sm3_256_final(void *hmac_sm3_256_ctx, uint8_t *hmac_value);
|
||||
|
||||
/**
|
||||
* Computes the HMAC-SM3-256 digest of a input data buffer.
|
||||
*
|
||||
* This function performs the HMAC-SM3-256 digest of a given data buffer, and places
|
||||
* the digest value into the specified memory.
|
||||
*
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] data Pointer to the buffer containing the data to be digested.
|
||||
* @param[in] data_size Size of data buffer in bytes.
|
||||
* @param[in] key Pointer to the user-supplied key.
|
||||
* @param[in] key_size Key size in bytes.
|
||||
* @param[out] hmac_value Pointer to a buffer that receives the HMAC-SM3-256 digest
|
||||
* value (32 bytes).
|
||||
*
|
||||
* @retval true HMAC-SM3-256 digest computation succeeded.
|
||||
* @retval false HMAC-SM3-256 digest computation failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_hmac_sm3_256_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value);
|
||||
#endif /* LIBSPDM_SM3_256_SUPPORT */
|
||||
|
||||
#endif /* CRYPTLIB_MAC_H */
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_RNG_H
|
||||
#define CRYPTLIB_RNG_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Random Number Generation Primitive
|
||||
*=====================================================================================*/
|
||||
|
||||
/**
|
||||
* Generates a random byte stream of the specified size. If initialization, testing, or seeding of
|
||||
* the (pseudo)random number generator is required it should be done before this function is called.
|
||||
*
|
||||
* If output is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[out] output Pointer to buffer to receive random value.
|
||||
* @param[in] size Size of random bytes to generate.
|
||||
*
|
||||
* @retval true Random byte stream generated successfully.
|
||||
* @retval false Generation of random byte stream failed.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_random_bytes(uint8_t *output, size_t size);
|
||||
|
||||
#endif /* CRYPTLIB_RNG_H */
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_RSA_H
|
||||
#define CRYPTLIB_RSA_H
|
||||
|
||||
/*=====================================================================================
|
||||
* RSA Cryptography Primitives
|
||||
*=====================================================================================
|
||||
*/
|
||||
|
||||
#if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
|
||||
/* RSA key Tags Definition used in libspdm_rsa_set_key() function for key component
|
||||
* identification.
|
||||
*/
|
||||
typedef enum {
|
||||
LIBSPDM_RSA_KEY_N, /*< RSA public Modulus (N)*/
|
||||
LIBSPDM_RSA_KEY_E, /*< RSA public exponent (e)*/
|
||||
LIBSPDM_RSA_KEY_D, /*< RSA Private exponent (d)*/
|
||||
LIBSPDM_RSA_KEY_P, /*< RSA secret prime factor of Modulus (p)*/
|
||||
LIBSPDM_RSA_KEY_Q, /*< RSA secret prime factor of Modules (q)*/
|
||||
LIBSPDM_RSA_KEY_DP, /*< p's CRT exponent (== d mod (p - 1))*/
|
||||
LIBSPDM_RSA_KEY_DQ, /*< q's CRT exponent (== d mod (q - 1))*/
|
||||
LIBSPDM_RSA_KEY_Q_INV /*< The CRT coefficient (== 1/q mod p)*/
|
||||
} libspdm_rsa_key_tag_t;
|
||||
|
||||
/**
|
||||
* Allocates and initializes one RSA context for subsequent use.
|
||||
*
|
||||
* @return Pointer to the RSA context that has been initialized.
|
||||
* If the allocations fails, libspdm_rsa_new() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_rsa_new(void);
|
||||
|
||||
/**
|
||||
* Release the specified RSA context.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
*
|
||||
* @param[in] rsa_context Pointer to the RSA context to be released.
|
||||
**/
|
||||
extern void libspdm_rsa_free(void *rsa_context);
|
||||
|
||||
/**
|
||||
* Sets the tag-designated key component into the established RSA context.
|
||||
*
|
||||
* This function sets the tag-designated RSA key component into the established
|
||||
* RSA context from the user-specified non-negative integer (octet string format
|
||||
* represented in RSA PKCS#1).
|
||||
* If big_number is NULL, then the specified key component in RSA context is cleared.
|
||||
* If rsa_context is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] rsa_context Pointer to RSA context being set.
|
||||
* @param[in] key_tag tag of RSA key component being set.
|
||||
* @param[in] big_number Pointer to octet integer buffer.
|
||||
* If NULL, then the specified key component in RSA
|
||||
* context is cleared.
|
||||
* @param[in] bn_size Size of big number buffer in bytes.
|
||||
* If big_number is NULL, then it is ignored.
|
||||
*
|
||||
* @retval true RSA key component was set successfully.
|
||||
* @retval false Invalid RSA key component tag.
|
||||
**/
|
||||
extern bool libspdm_rsa_set_key(void *rsa_context, const libspdm_rsa_key_tag_t key_tag,
|
||||
const uint8_t *big_number, size_t bn_size);
|
||||
|
||||
/**
|
||||
* Gets the tag-designated RSA key component from the established RSA context.
|
||||
*
|
||||
* This function retrieves the tag-designated RSA key component from the
|
||||
* established RSA context as a non-negative integer (octet string format
|
||||
* represented in RSA PKCS#1).
|
||||
* If specified key component has not been set or has been cleared, then returned
|
||||
* bn_size is set to 0.
|
||||
* If the big_number buffer is too small to hold the contents of the key, false
|
||||
* is returned and bn_size is set to the required buffer size to obtain the key.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If bn_size is NULL, then return false.
|
||||
* If bn_size is large enough but big_number is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] rsa_context Pointer to RSA context being set.
|
||||
* @param[in] key_tag Tag of RSA key component being set.
|
||||
* @param[out] big_number Pointer to octet integer buffer.
|
||||
* @param[in, out] bn_size On input, the size of big number buffer in bytes.
|
||||
* On output, the size of data returned in big number buffer in bytes.
|
||||
*
|
||||
* @retval true RSA key component was retrieved successfully.
|
||||
* @retval false Invalid RSA key component tag.
|
||||
* @retval false bn_size is too small.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_rsa_get_key(void *rsa_context, const libspdm_rsa_key_tag_t key_tag,
|
||||
uint8_t *big_number, size_t *bn_size);
|
||||
|
||||
/**
|
||||
* Generates RSA key components.
|
||||
*
|
||||
* This function generates RSA key components. It takes RSA public exponent E and
|
||||
* length in bits of RSA modulus N as input, and generates all key components.
|
||||
* If public_exponent is NULL, the default RSA public exponent (0x10001) will be used.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in, out] rsa_context Pointer to RSA context being set.
|
||||
* @param[in] modulus_length Length of RSA modulus N in bits.
|
||||
* @param[in] public_exponent Pointer to RSA public exponent.
|
||||
* @param[in] public_exponent_size Size of RSA public exponent buffer in bytes.
|
||||
*
|
||||
* @retval true RSA key component was generated successfully.
|
||||
* @retval false Invalid RSA key component tag.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_rsa_generate_key(void *rsa_context, size_t modulus_length,
|
||||
const uint8_t *public_exponent,
|
||||
size_t public_exponent_size);
|
||||
|
||||
/**
|
||||
* Validates key components of RSA context.
|
||||
* NOTE: This function performs integrity checks on all the RSA key material, so
|
||||
* the RSA key structure must contain all the private key data.
|
||||
*
|
||||
* This function validates key components of RSA context in following aspects:
|
||||
* - Whether p is a prime
|
||||
* - Whether q is a prime
|
||||
* - Whether n = p * q
|
||||
* - Whether d*e = 1 mod lcm(p-1,q-1)
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] rsa_context Pointer to RSA context to check.
|
||||
*
|
||||
* @retval true RSA key components are valid.
|
||||
* @retval false RSA key components are not valid.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_rsa_check_key(void *rsa_context);
|
||||
#endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
|
||||
|
||||
#if LIBSPDM_RSA_SSA_SUPPORT
|
||||
/**
|
||||
* Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
|
||||
*
|
||||
* This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme
|
||||
* defined in RSA PKCS#1. If the signature buffer is too small to hold the contents of signature,
|
||||
* false is returned and sig_size is set to the required buffer size to obtain the signature.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If message_hash is NULL, then return false.
|
||||
* If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256,
|
||||
* SHA3_384, SHA3_512.
|
||||
* If sig_size is large enough but signature is NULL, then return false.
|
||||
* If this interface is not supported, then return false.
|
||||
*
|
||||
* @param[in] rsa_context Pointer to RSA context for signature generation.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] message_hash Pointer to octet message hash to be signed.
|
||||
* @param[in] hash_size Size of the message hash in bytes.
|
||||
* @param[out] signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.
|
||||
* @param[in, out] sig_size On input, the size of signature buffer in bytes.
|
||||
* On output, the size of data returned in signature buffer in bytes.
|
||||
*
|
||||
* @retval true signature successfully generated in PKCS1-v1_5.
|
||||
* @retval false signature generation failed.
|
||||
* @retval false sig_size is too small.
|
||||
* @retval false This interface is not supported.
|
||||
**/
|
||||
extern bool libspdm_rsa_pkcs1_sign_with_nid(void *rsa_context, size_t hash_nid,
|
||||
const uint8_t *message_hash,
|
||||
size_t hash_size, uint8_t *signature,
|
||||
size_t *sig_size);
|
||||
|
||||
/**
|
||||
* Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in RSA PKCS#1.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If message_hash is NULL, then return false.
|
||||
* If signature is NULL, then return false.
|
||||
* If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256,
|
||||
* SHA3_384, SHA3_512.
|
||||
*
|
||||
* @param[in] rsa_context Pointer to RSA context for signature verification.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] message_hash Pointer to octet message hash to be checked.
|
||||
* @param[in] hash_size Size of the message hash in bytes.
|
||||
* @param[in] signature Pointer to RSA PKCS1-v1_5 signature to be verified.
|
||||
* @param[in] sig_size Size of signature in bytes.
|
||||
*
|
||||
* @retval true Valid signature encoded in PKCS1-v1_5.
|
||||
* @retval false Invalid signature or invalid RSA context.
|
||||
**/
|
||||
extern bool libspdm_rsa_pkcs1_verify_with_nid(void *rsa_context, size_t hash_nid,
|
||||
const uint8_t *message_hash,
|
||||
size_t hash_size, const uint8_t *signature,
|
||||
size_t sig_size);
|
||||
#endif /* LIBSPDM_RSA_SSA_SUPPORT */
|
||||
|
||||
#if LIBSPDM_RSA_PSS_SUPPORT
|
||||
/**
|
||||
* Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
|
||||
*
|
||||
* This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined
|
||||
* in RSA PKCS#1 v2.2.
|
||||
*
|
||||
* The salt length is same as digest length.
|
||||
*
|
||||
* If the signature buffer is too small to hold the contents of signature, false
|
||||
* is returned and sig_size is set to the required buffer size to obtain the signature.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If message_hash is NULL, then return false.
|
||||
* If hash_size need match the hash_nid. nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384,
|
||||
* SHA3_512.
|
||||
* If sig_size is large enough but signature is NULL, then return false.
|
||||
*
|
||||
* @param[in] rsa_context Pointer to RSA context for signature generation.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] message_hash Pointer to octet message hash to be signed.
|
||||
* @param[in] hash_size Size of the message hash in bytes.
|
||||
* @param[out] signature Pointer to buffer to receive RSA-SSA PSS signature.
|
||||
* @param[in, out] sig_size On input, the size of signature buffer in bytes.
|
||||
* On output, the size of data returned in signature buffer in bytes.
|
||||
*
|
||||
* @retval true signature successfully generated in RSA-SSA PSS.
|
||||
* @retval false signature generation failed.
|
||||
* @retval false sig_size is too small.
|
||||
**/
|
||||
extern bool libspdm_rsa_pss_sign(void *rsa_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
uint8_t *signature, size_t *sig_size);
|
||||
|
||||
/**
|
||||
* Verifies the RSA-SSA signature with EMSA-PSS encoding scheme defined in
|
||||
* RSA PKCS#1 v2.2.
|
||||
*
|
||||
* The salt length is same as digest length.
|
||||
*
|
||||
* If rsa_context is NULL, then return false.
|
||||
* If message_hash is NULL, then return false.
|
||||
* If signature is NULL, then return false.
|
||||
* If hash_size need match the hash_nid. nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384,
|
||||
* SHA3_512.
|
||||
*
|
||||
* @param[in] rsa_context Pointer to RSA context for signature verification.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] message_hash Pointer to octet message hash to be checked.
|
||||
* @param[in] hash_size Size of the message hash in bytes.
|
||||
* @param[in] signature Pointer to RSA-SSA PSS signature to be verified.
|
||||
* @param[in] sig_size Size of signature in bytes.
|
||||
*
|
||||
* @retval true Valid signature encoded in RSA-SSA PSS.
|
||||
* @retval false Invalid signature or invalid RSA context.
|
||||
**/
|
||||
extern bool libspdm_rsa_pss_verify(void *rsa_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
const uint8_t *signature, size_t sig_size);
|
||||
#endif /* LIBSPDM_RSA_PSS_SUPPORT */
|
||||
#endif /* CRYPTLIB_RSA_H */
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_SM2_H
|
||||
#define CRYPTLIB_SM2_H
|
||||
|
||||
/*=====================================================================================
|
||||
* Shang-Mi2 Primitives
|
||||
*=====================================================================================*/
|
||||
|
||||
#if LIBSPDM_SM2_DSA_SUPPORT
|
||||
/**
|
||||
* Allocates and Initializes one Shang-Mi2 context for subsequent use.
|
||||
*
|
||||
* @param nid cipher NID
|
||||
*
|
||||
* @return Pointer to the Shang-Mi2 context that has been initialized.
|
||||
* If the allocations fails, sm2_new_by_nid() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sm2_dsa_new_by_nid(size_t nid);
|
||||
|
||||
/**
|
||||
* Release the specified sm2 context.
|
||||
*
|
||||
* @param[in] sm2_context Pointer to the sm2 context to be released.
|
||||
**/
|
||||
extern void libspdm_sm2_dsa_free(void *sm2_context);
|
||||
|
||||
/**
|
||||
* Carries out the SM2 signature, based upon GB/T 32918.2-2016: SM2 - Part2.
|
||||
*
|
||||
* This function carries out the SM2 signature.
|
||||
* If the signature buffer is too small to hold the contents of signature, false
|
||||
* is returned and sig_size is set to the required buffer size to obtain the signature.
|
||||
*
|
||||
* If sm2_context is NULL, then return false.
|
||||
* If message is NULL, then return false.
|
||||
* hash_nid must be SM3_256.
|
||||
* If sig_size is large enough but signature is NULL, then return false.
|
||||
*
|
||||
* The id_a_size must be smaller than 2^16-1.
|
||||
* The sig_size is 64. first 32-byte is R, second 32-byte is S.
|
||||
*
|
||||
* @param[in] sm2_context Pointer to sm2 context for signature generation.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] id_a The ID-A of the signing context.
|
||||
* @param[in] id_a_size Size of ID-A signing context.
|
||||
* @param[in] message Pointer to octet message to be signed (before hash).
|
||||
* @param[in] size Size of the message in bytes.
|
||||
* @param[out] signature Pointer to buffer to receive SM2 signature.
|
||||
* @param[in, out] sig_size On input, the size of signature buffer in bytes.
|
||||
* On output, the size of data returned in signature buffer in bytes.
|
||||
*
|
||||
* @retval true signature successfully generated in SM2.
|
||||
* @retval false signature generation failed.
|
||||
* @retval false sig_size is too small.
|
||||
**/
|
||||
extern bool libspdm_sm2_dsa_sign(const void *sm2_context, size_t hash_nid,
|
||||
const uint8_t *id_a, size_t id_a_size,
|
||||
const uint8_t *message, size_t size,
|
||||
uint8_t *signature, size_t *sig_size);
|
||||
|
||||
/**
|
||||
* Verifies the SM2 signature, based upon GB/T 32918.2-2016: SM2 - Part2.
|
||||
*
|
||||
* If sm2_context is NULL, then return false.
|
||||
* If message is NULL, then return false.
|
||||
* If signature is NULL, then return false.
|
||||
* hash_nid must be SM3_256.
|
||||
*
|
||||
* The id_a_size must be smaller than 2^16-1.
|
||||
* The sig_size is 64. first 32-byte is R, second 32-byte is S.
|
||||
*
|
||||
* @param[in] sm2_context Pointer to SM2 context for signature verification.
|
||||
* @param[in] hash_nid hash NID
|
||||
* @param[in] id_a The ID-A of the signing context.
|
||||
* @param[in] id_a_size Size of ID-A signing context.
|
||||
* @param[in] message Pointer to octet message to be checked (before hash).
|
||||
* @param[in] size Size of the message in bytes.
|
||||
* @param[in] signature Pointer to SM2 signature to be verified.
|
||||
* @param[in] sig_size Size of signature in bytes.
|
||||
*
|
||||
* @retval true Valid signature encoded in SM2.
|
||||
* @retval false Invalid signature or invalid sm2 context.
|
||||
*
|
||||
**/
|
||||
extern bool libspdm_sm2_dsa_verify(const void *sm2_context, size_t hash_nid,
|
||||
const uint8_t *id_a, size_t id_a_size,
|
||||
const uint8_t *message, size_t size,
|
||||
const uint8_t *signature, size_t sig_size);
|
||||
#endif /* LIBSPDM_SM2_DSA_SUPPORT */
|
||||
|
||||
#if LIBSPDM_SM2_KEY_EXCHANGE_SUPPORT
|
||||
/**
|
||||
* Allocates and Initializes one Shang-Mi2 context for subsequent use.
|
||||
*
|
||||
* @param nid cipher NID
|
||||
*
|
||||
* @return Pointer to the Shang-Mi2 context that has been initialized.
|
||||
* If the allocations fails, sm2_new_by_nid() returns NULL.
|
||||
**/
|
||||
extern void *libspdm_sm2_key_exchange_new_by_nid(size_t nid);
|
||||
|
||||
/**
|
||||
* Release the specified sm2 context.
|
||||
*
|
||||
* @param[in] sm2_context Pointer to the sm2 context to be released.
|
||||
*
|
||||
**/
|
||||
extern void libspdm_sm2_key_exchange_free(void *sm2_context);
|
||||
|
||||
/**
|
||||
* Initialize the specified sm2 context.
|
||||
*
|
||||
* @param[in] sm2_context Pointer to the sm2 context to be released.
|
||||
* @param[in] hash_nid hash NID, only SM3 is valid.
|
||||
* @param[in] id_a The ID-A of the key exchange context.
|
||||
* @param[in] id_a_size Size of ID-A key exchange context.
|
||||
* @param[in] id_b The ID-B of the key exchange context.
|
||||
* @param[in] id_b_size Size of ID-B key exchange context.
|
||||
* @param[in] is_initiator If the caller is initiator.
|
||||
*
|
||||
* @retval true sm2 context is initialized.
|
||||
* @retval false sm2 context is not initialized.
|
||||
**/
|
||||
extern bool libspdm_sm2_key_exchange_init(const void *sm2_context, size_t hash_nid,
|
||||
const uint8_t *id_a, size_t id_a_size,
|
||||
const uint8_t *id_b, size_t id_b_size,
|
||||
bool is_initiator);
|
||||
|
||||
/**
|
||||
* Generates sm2 key and returns sm2 public key (X, Y), based upon GB/T 32918.3-2016: SM2 - Part3.
|
||||
*
|
||||
* This function generates random secret, and computes the public key (X, Y), which is
|
||||
* returned via parameter public, public_size.
|
||||
* X is the first half of public with size being public_size / 2,
|
||||
* Y is the second half of public with size being public_size / 2.
|
||||
* sm2 context is updated accordingly.
|
||||
* If the public buffer is too small to hold the public X, Y, false is returned and
|
||||
* public_size is set to the required buffer size to obtain the public X, Y.
|
||||
*
|
||||
* The public_size is 64. first 32-byte is X, second 32-byte is Y.
|
||||
*
|
||||
* If sm2_context is NULL, then return false.
|
||||
* If public_size is NULL, then return false.
|
||||
* If public_size is large enough but public is NULL, then return false.
|
||||
*
|
||||
* @param[in, out] sm2_context Pointer to the sm2 context.
|
||||
* @param[out] public_data Pointer to the buffer to receive generated public X,Y.
|
||||
* @param[in, out] public_size On input, the size of public buffer in bytes.
|
||||
* On output, the size of data returned in public buffer in bytes.
|
||||
*
|
||||
* @retval true sm2 public X,Y generation succeeded.
|
||||
* @retval false sm2 public X,Y generation failed.
|
||||
* @retval false public_size is not large enough.
|
||||
**/
|
||||
extern bool libspdm_sm2_key_exchange_generate_key(void *sm2_context, uint8_t *public_data,
|
||||
size_t *public_size);
|
||||
|
||||
/**
|
||||
* Computes exchanged common key, based upon GB/T 32918.3-2016: SM2 - Part3.
|
||||
*
|
||||
* Given peer's public key (X, Y), this function computes the exchanged common key,
|
||||
* based on its own context including value of curve parameter and random secret.
|
||||
* X is the first half of peer_public with size being peer_public_size / 2,
|
||||
* Y is the second half of peer_public with size being peer_public_size / 2.
|
||||
*
|
||||
* If sm2_context is NULL, then return false.
|
||||
* If peer_public is NULL, then return false.
|
||||
* If peer_public_size is 0, then return false.
|
||||
* If key is NULL, then return false.
|
||||
*
|
||||
* The id_a_size and id_b_size must be smaller than 2^16-1.
|
||||
* The peer_public_size is 64. first 32-byte is X, second 32-byte is Y.
|
||||
* The key_size must be smaller than 2^32-1, limited by KDF function.
|
||||
*
|
||||
* @param[in, out] sm2_context Pointer to the sm2 context.
|
||||
* @param[in] peer_public Pointer to the peer's public X,Y.
|
||||
* @param[in] peer_public_size Size of peer's public X,Y in bytes.
|
||||
* @param[out] key Pointer to the buffer to receive generated key.
|
||||
* @param[in] key_size On input, the size of key buffer in bytes.
|
||||
*
|
||||
* @retval true sm2 exchanged key generation succeeded.
|
||||
* @retval false sm2 exchanged key generation failed.
|
||||
**/
|
||||
extern bool libspdm_sm2_key_exchange_compute_key(void *sm2_context,
|
||||
const uint8_t *peer_public,
|
||||
size_t peer_public_size, uint8_t *key,
|
||||
size_t *key_size);
|
||||
#endif /* LIBSPDM_SM2_KEY_EXCHANGE_SUPPORT */
|
||||
#endif /* CRYPTLIB_SM2_H */
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "linux_nvswitch.h"
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
||||
#define NVSWITCH_I2C_GET_PARENT(adapter) \
|
||||
(NVSWITCH_DEV *)pci_get_drvdata(to_pci_dev((adapter)->dev.parent));
|
||||
|
||||
#define NVSWITCH_I2C_GET_ALGO_DATA(adapter) \
|
||||
(nvswitch_i2c_algo_data *)(adapter)->algo_data;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU32 port;
|
||||
} nvswitch_i2c_algo_data;
|
||||
|
||||
static int
|
||||
nvswitch_i2c_algo_master_xfer
|
||||
(
|
||||
struct i2c_adapter *adapter,
|
||||
struct i2c_msg msgs[],
|
||||
int num
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
NvU32 port;
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
nvswitch_i2c_algo_data *i2c_algo_data;
|
||||
NVSWITCH_DEV *nvswitch_dev;
|
||||
const unsigned int supported_i2c_flags = I2C_M_RD
|
||||
#if defined (I2C_M_DMA_SAFE)
|
||||
| I2C_M_DMA_SAFE
|
||||
#endif
|
||||
;
|
||||
|
||||
nvswitch_dev = NVSWITCH_I2C_GET_PARENT(adapter);
|
||||
if (nvswitch_dev == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = mutex_lock_interruptible(&nvswitch_dev->device_mutex);
|
||||
if (rc)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (nvswitch_dev->unusable)
|
||||
{
|
||||
printk(KERN_INFO "%s: a stale fd detected\n", nvswitch_dev->name);
|
||||
status = NVL_ERR_INVALID_STATE;
|
||||
goto nvswitch_i2c_algo_master_xfer_exit;
|
||||
}
|
||||
|
||||
i2c_algo_data = NVSWITCH_I2C_GET_ALGO_DATA(adapter);
|
||||
if (i2c_algo_data == NULL)
|
||||
{
|
||||
status = NVL_ERR_INVALID_STATE;
|
||||
goto nvswitch_i2c_algo_master_xfer_exit;
|
||||
}
|
||||
|
||||
port = i2c_algo_data->port;
|
||||
|
||||
for (i = 0; (i < num) && (status == NVL_SUCCESS); i++)
|
||||
{
|
||||
if (msgs[i].flags & ~supported_i2c_flags)
|
||||
{
|
||||
status = NVL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = nvswitch_lib_i2c_transfer(nvswitch_dev->lib_device, port,
|
||||
(msgs[i].flags & I2C_M_RD) ?
|
||||
NVSWITCH_I2C_CMD_READ : NVSWITCH_I2C_CMD_WRITE,
|
||||
(NvU8)(msgs[i].addr & 0x7f), 0,
|
||||
(NvU32)(msgs[i].len & 0xffffUL),
|
||||
(NvU8 *)msgs[i].buf);
|
||||
}
|
||||
}
|
||||
|
||||
nvswitch_i2c_algo_master_xfer_exit:
|
||||
mutex_unlock(&nvswitch_dev->device_mutex);
|
||||
|
||||
rc = nvswitch_map_status(status);
|
||||
return (rc == 0) ? num : rc;
|
||||
}
|
||||
|
||||
static int
|
||||
nvswitch_i2c_algo_smbus_xfer
|
||||
(
|
||||
struct i2c_adapter *adapter,
|
||||
u16 addr,
|
||||
unsigned short flags,
|
||||
char read_write,
|
||||
u8 command,
|
||||
int protocol,
|
||||
union i2c_smbus_data *data
|
||||
)
|
||||
{
|
||||
int rc = -EIO;
|
||||
NvU32 port;
|
||||
NvU8 cmd;
|
||||
NvU32 len;
|
||||
NvU8 type;
|
||||
NvU8 *xfer_data;
|
||||
NvlStatus status = NVL_SUCCESS;
|
||||
nvswitch_i2c_algo_data *i2c_algo_data;
|
||||
NVSWITCH_DEV *nvswitch_dev;
|
||||
|
||||
nvswitch_dev = NVSWITCH_I2C_GET_PARENT(adapter);
|
||||
if (nvswitch_dev == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = mutex_lock_interruptible(&nvswitch_dev->device_mutex);
|
||||
if (rc)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (nvswitch_dev->unusable)
|
||||
{
|
||||
printk(KERN_INFO "%s: a stale fd detected\n", nvswitch_dev->name);
|
||||
status = NVL_ERR_INVALID_STATE;
|
||||
goto nvswitch_i2c_algo_smbus_xfer_exit;
|
||||
}
|
||||
|
||||
i2c_algo_data = NVSWITCH_I2C_GET_ALGO_DATA(adapter);
|
||||
if (i2c_algo_data == NULL)
|
||||
{
|
||||
status = NVL_ERR_INVALID_STATE;
|
||||
goto nvswitch_i2c_algo_smbus_xfer_exit;
|
||||
}
|
||||
|
||||
port = i2c_algo_data->port;
|
||||
|
||||
switch (protocol)
|
||||
{
|
||||
case I2C_SMBUS_QUICK:
|
||||
{
|
||||
cmd = 0;
|
||||
len = 0;
|
||||
type = (read_write == I2C_SMBUS_READ) ?
|
||||
NVSWITCH_I2C_CMD_SMBUS_QUICK_READ :
|
||||
NVSWITCH_I2C_CMD_SMBUS_QUICK_WRITE;
|
||||
xfer_data = NULL;
|
||||
break;
|
||||
}
|
||||
case I2C_SMBUS_BYTE:
|
||||
{
|
||||
cmd = 0;
|
||||
len = 1;
|
||||
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
{
|
||||
type = NVSWITCH_I2C_CMD_READ;
|
||||
xfer_data = (NvU8 *)&data->byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = NVSWITCH_I2C_CMD_WRITE;
|
||||
xfer_data = &command;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
{
|
||||
cmd = (NvU8)command;
|
||||
len = 1;
|
||||
type = (read_write == I2C_SMBUS_READ) ?
|
||||
NVSWITCH_I2C_CMD_SMBUS_READ :
|
||||
NVSWITCH_I2C_CMD_SMBUS_WRITE;
|
||||
cmd = (NvU8)command;
|
||||
xfer_data = (NvU8 *)&data->byte;
|
||||
break;
|
||||
}
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
{
|
||||
cmd = (NvU8)command;
|
||||
len = 2;
|
||||
type = (read_write == I2C_SMBUS_READ) ?
|
||||
NVSWITCH_I2C_CMD_SMBUS_READ :
|
||||
NVSWITCH_I2C_CMD_SMBUS_WRITE;
|
||||
xfer_data = (NvU8 *)&data->word;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
status = NVL_BAD_ARGS;
|
||||
goto nvswitch_i2c_algo_smbus_xfer_exit;
|
||||
}
|
||||
}
|
||||
|
||||
status = nvswitch_lib_i2c_transfer(nvswitch_dev->lib_device, port,
|
||||
type, (NvU8)(addr & 0x7f),
|
||||
cmd, len, (NvU8 *)xfer_data);
|
||||
|
||||
nvswitch_i2c_algo_smbus_xfer_exit:
|
||||
mutex_unlock(&nvswitch_dev->device_mutex);
|
||||
|
||||
return nvswitch_map_status(status);
|
||||
}
|
||||
|
||||
static u32 nvswitch_i2c_algo_functionality(struct i2c_adapter *adapter)
|
||||
{
|
||||
return (I2C_FUNC_I2C |
|
||||
I2C_FUNC_SMBUS_QUICK |
|
||||
I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA);
|
||||
}
|
||||
|
||||
static struct i2c_algorithm nvswitch_i2c_algo = {
|
||||
.master_xfer = nvswitch_i2c_algo_master_xfer,
|
||||
.smbus_xfer = nvswitch_i2c_algo_smbus_xfer,
|
||||
.functionality = nvswitch_i2c_algo_functionality,
|
||||
};
|
||||
|
||||
struct i2c_adapter nvswitch_i2c_adapter_prototype = {
|
||||
.owner = THIS_MODULE,
|
||||
.algo = &nvswitch_i2c_algo,
|
||||
.algo_data = NULL,
|
||||
};
|
||||
|
||||
struct i2c_adapter *
|
||||
nvswitch_i2c_add_adapter
|
||||
(
|
||||
NVSWITCH_DEV *nvswitch_dev,
|
||||
NvU32 port
|
||||
)
|
||||
{
|
||||
struct i2c_adapter *adapter = NULL;
|
||||
int rc = 0;
|
||||
struct pci_dev *pci_dev;
|
||||
nvswitch_i2c_algo_data *i2c_algo_data = NULL;
|
||||
|
||||
if (nvswitch_dev == NULL)
|
||||
{
|
||||
printk(KERN_ERR "nvswitch_dev is NULL!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
adapter = nvswitch_os_malloc(sizeof(struct i2c_adapter));
|
||||
if (adapter == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nvswitch_os_memcpy(adapter,
|
||||
&nvswitch_i2c_adapter_prototype,
|
||||
sizeof(struct i2c_adapter));
|
||||
|
||||
i2c_algo_data = nvswitch_os_malloc(sizeof(nvswitch_i2c_algo_data));
|
||||
if (i2c_algo_data == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
i2c_algo_data->port = port;
|
||||
pci_dev = nvswitch_dev->pci_dev;
|
||||
adapter->dev.parent = &pci_dev->dev;
|
||||
adapter->algo_data = (void *)i2c_algo_data;
|
||||
|
||||
rc = nvswitch_os_snprintf(adapter->name,
|
||||
sizeof(adapter->name),
|
||||
"NVIDIA NVSwitch i2c adapter %u at %04x:%x:%02x.%u",
|
||||
port,
|
||||
NV_PCI_DOMAIN_NUMBER(pci_dev),
|
||||
NV_PCI_BUS_NUMBER(pci_dev),
|
||||
NV_PCI_SLOT_NUMBER(pci_dev),
|
||||
PCI_FUNC(pci_dev->devfn));
|
||||
if ((rc < 0) && (rc >= sizeof(adapter->name)))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = i2c_add_adapter(adapter);
|
||||
if (rc < 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return adapter;
|
||||
|
||||
cleanup:
|
||||
nvswitch_os_free(i2c_algo_data);
|
||||
nvswitch_os_free(adapter);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_i2c_del_adapter
|
||||
(
|
||||
struct i2c_adapter *adapter
|
||||
)
|
||||
{
|
||||
if (adapter != NULL)
|
||||
{
|
||||
nvswitch_os_free(adapter->algo_data);
|
||||
i2c_del_adapter(adapter);
|
||||
nvswitch_os_free(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
#else // (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE))
|
||||
|
||||
struct i2c_adapter *
|
||||
nvswitch_i2c_add_adapter
|
||||
(
|
||||
NVSWITCH_DEV *nvswitch_dev,
|
||||
NvU32 port
|
||||
)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_i2c_del_adapter
|
||||
(
|
||||
struct i2c_adapter *adapter
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE))
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef LIBSPDM_LIB_CONFIG_H
|
||||
#define LIBSPDM_LIB_CONFIG_H
|
||||
|
||||
#ifndef LIBSPDM_CONFIG
|
||||
#include "library/spdm_lib_config.h"
|
||||
#else
|
||||
#include LIBSPDM_CONFIG
|
||||
#endif
|
||||
|
||||
#if defined(LIBSPDM_ENABLE_SET_CERTIFICATE_CAP) && \
|
||||
!defined(LIBSPDM_ENABLE_CAPABILITY_SET_CERTIFICATE_CAP)
|
||||
#ifdef _MSC_VER
|
||||
#pragma message("LIBSPDM_ENABLE_SET_CERTIFICATE_CAP is deprecated. Use " \
|
||||
"LIBSPDM_ENABLE_CAPABILITY_SET_CERTIFICATE_CAP instead. This warning will be removed in a " \
|
||||
"future release.")
|
||||
#else
|
||||
#warning LIBSPDM_ENABLE_SET_CERTIFICATE_CAP is deprecated. Use \
|
||||
LIBSPDM_ENABLE_CAPABILITY_SET_CERTIFICATE_CAP instead. This warning will be removed in a \
|
||||
future release.
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* defined(LIBSPDM_ENABLE_SET_CERTIFICATE_CAP) */
|
||||
|
||||
#if defined(LIBSPDM_ENABLE_CHUNK_CAP) && !defined(LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP)
|
||||
#ifdef _MSC_VER
|
||||
#pragma message("LIBSPDM_ENABLE_CHUNK_CAP is deprecated. Use LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP " \
|
||||
"instead. This warning will be removed in a future release.")
|
||||
#else
|
||||
#warning LIBSPDM_ENABLE_CHUNK_CAP is deprecated. Use LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP \
|
||||
instead. This warning will be removed in a future release.
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* defined(LIBSPDM_ENABLE_CHUNK_CAP) */
|
||||
|
||||
#if defined(MDEPKG_NDEBUG) && !defined(LIBSPDM_DEBUG_ENABLE)
|
||||
#ifdef _MSC_VER
|
||||
#pragma message("MDEPKG_NDEBUG is deprecated. Use LIBSPDM_DEBUG_ENABLE " \
|
||||
"instead. This warning will be removed in a future release.")
|
||||
#else
|
||||
#warning MDEPKG_NDEBUG is deprecated. Use LIBSPDM_DEBUG_ENABLE \
|
||||
instead. This warning will be removed in a future release.
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* defined(MDEPKG_NDEBUG) */
|
||||
|
||||
#if defined(LIBSPDM_DEBUG_ENABLE)
|
||||
#undef LIBSPDM_DEBUG_ASSERT_ENABLE
|
||||
#undef LIBSPDM_DEBUG_PRINT_ENABLE
|
||||
#undef LIBSPDM_DEBUG_BLOCK_ENABLE
|
||||
|
||||
#define LIBSPDM_DEBUG_ASSERT_ENABLE (LIBSPDM_DEBUG_ENABLE)
|
||||
#define LIBSPDM_DEBUG_PRINT_ENABLE (LIBSPDM_DEBUG_ENABLE)
|
||||
#define LIBSPDM_DEBUG_BLOCK_ENABLE (LIBSPDM_DEBUG_ENABLE)
|
||||
#elif defined(MDEPKG_NDEBUG)
|
||||
#undef LIBSPDM_DEBUG_ASSERT_ENABLE
|
||||
#undef LIBSPDM_DEBUG_PRINT_ENABLE
|
||||
#undef LIBSPDM_DEBUG_BLOCK_ENABLE
|
||||
|
||||
#define LIBSPDM_DEBUG_ASSERT_ENABLE 0
|
||||
#define LIBSPDM_DEBUG_PRINT_ENABLE 0
|
||||
#define LIBSPDM_DEBUG_BLOCK_ENABLE 0
|
||||
#endif /* defined(LIBSPDM_DEBUG_ENABLE) */
|
||||
|
||||
#if LIBSPDM_CHECK_MACRO
|
||||
#include "internal/libspdm_macro_check.h"
|
||||
#endif /* LIBSPDM_CHECK_MACRO */
|
||||
|
||||
#endif /* LIBSPDM_LIB_CONFIG_H */
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __INTERNAL_CRYPT_LIB_H__
|
||||
#define __INTERNAL_CRYPT_LIB_H__
|
||||
|
||||
/*
|
||||
* This code uses Linux Kernel Crypto API extensively. Web page written by
|
||||
* Stephan Mueller and Marek Vasut is a good starting reference on how linux
|
||||
* kernel provides crypto api.
|
||||
*/
|
||||
#include "conftest.h"
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
// Check if ECDH/ECDSA are there, on some platforms they might not be...
|
||||
#ifndef AUTOCONF_INCLUDED
|
||||
#if defined(NV_GENERATED_AUTOCONF_H_PRESENT)
|
||||
#include <generated/autoconf.h>
|
||||
#else
|
||||
#include <linux/autoconf.h>
|
||||
#endif
|
||||
#endif
|
||||
#if \
|
||||
(defined(CONFIG_CRYPTO_AEAD) || defined(CONFIG_CRYPTO_AEAD_MODULE)) && \
|
||||
(defined(CONFIG_CRYPTO_AKCIPHER) || defined(CONFIG_CRYPTO_AKCIPHER_MODULE)) && \
|
||||
(defined(CONFIG_CRYPTO_SKCIPHER) || defined(CONFIG_CRYPTO_SKCIPHER_MODULE)) && \
|
||||
(defined(CONFIG_CRYPTO_HASH) || defined(CONFIG_CRYPTO_HASH_MODULE)) && \
|
||||
(defined(CONFIG_CRYPTO_HMAC) || defined(CONFIG_CRYPTO_HMAC_MODULE)) && \
|
||||
(defined(CONFIG_CRYPTO_ECDH) || defined(CONFIG_CRYPTO_ECDH_MODULE)) && \
|
||||
(defined(CONFIG_CRYPTO_ECDSA) || defined(CONFIG_CRYPTO_ECDSA_MODULE)) && \
|
||||
(defined(CONFIG_X509_CERTIFICATE_PARSER) || defined(CONFIG_X509_CERTIFICATE_PARSER_MODULE))
|
||||
#define NV_CONFIG_CRYPTO_PRESENT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* It is possible that we don't have access to all the functions we have. This
|
||||
* could be either because we are running non-gpl kernel, because kernel is too
|
||||
* old or even just user disabled. If we should use LKCA, include headers, else
|
||||
* define stubs to return errors.
|
||||
*/
|
||||
#if defined(NV_CRYPTO_PRESENT) && defined (NV_CONFIG_CRYPTO_PRESENT)
|
||||
#define USE_LKCA 1
|
||||
#endif
|
||||
|
||||
#ifdef USE_LKCA
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <crypto/aead.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/sm3.h>
|
||||
|
||||
// HASH_MAX_DIGESTSIZE is available since 4.20.
|
||||
// This value is accurate as of 6.1
|
||||
#ifndef HASH_MAX_DIGESTSIZE
|
||||
#define HASH_MAX_DIGESTSIZE 64
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Just stub everything out
|
||||
struct shash_desc;
|
||||
struct crypto_shash;
|
||||
#define crypto_shash_setkey(...) -ENOMEM
|
||||
#define crypto_shash_init(...) -ENOMEM
|
||||
#define crypto_shash_update(...) -ENOMEM
|
||||
#define crypto_shash_update(...) -ENOMEM
|
||||
#define crypto_shash_final(...) -ENOMEM
|
||||
#endif
|
||||
|
||||
#define CHAR_BIT 8U
|
||||
#undef SIZE_MAX
|
||||
#define SIZE_MAX 8
|
||||
|
||||
#include "library/cryptlib.h"
|
||||
|
||||
#define LIBSPDM_ASSERT(...)
|
||||
struct lkca_aead_ctx;
|
||||
int lkca_aead_alloc(struct lkca_aead_ctx **ctx, char const *alg);
|
||||
void lkca_aead_free(struct lkca_aead_ctx *ctx);
|
||||
int lkca_aead_ex(struct lkca_aead_ctx *ctx,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size,
|
||||
bool enc);
|
||||
|
||||
int libspdm_aead(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size,
|
||||
bool enc, char const *alg);
|
||||
|
||||
void *lkca_hash_new(const char* alg_name);
|
||||
void lkca_hash_free(struct shash_desc *ctx);
|
||||
bool lkca_hash_duplicate(struct shash_desc *dst, struct shash_desc const *src);
|
||||
bool lkca_hash_all(const char* alg_name, const void *data,
|
||||
size_t data_size, uint8_t *hash_value);
|
||||
bool lkca_hmac_duplicate(struct shash_desc *dst, struct shash_desc const *src);
|
||||
bool lkca_hmac_set_key(struct shash_desc *ctx, const uint8_t *key, size_t key_size);
|
||||
bool lkca_hmac_all(const char* alg_name, const uint8_t *key, size_t key_size,
|
||||
const uint8_t *data, size_t data_size, uint8_t *hash_value);
|
||||
bool lkca_hkdf_extract_and_expand(const char *alg_name,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
bool lkca_hkdf_expand(const char *alg_name,
|
||||
const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size);
|
||||
|
||||
|
||||
bool lkca_ecdsa_set_priv_key(void *context, uint8_t *key, size_t key_size);
|
||||
bool lkca_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
|
||||
size_t public_key_size);
|
||||
bool lkca_ec_get_pub_key(void *ec_context, uint8_t *public_key,
|
||||
size_t *public_key_size);
|
||||
bool lkca_ec_generate_key(void *ec_context, uint8_t *public_data,
|
||||
size_t *public_size);
|
||||
bool lkca_ec_compute_key(void *ec_context, const uint8_t *peer_public,
|
||||
size_t peer_public_size, uint8_t *key,
|
||||
size_t *key_size);
|
||||
bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
const uint8_t *signature, size_t sig_size);
|
||||
#endif
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _IOCTL_COMMON_NVSWITCH_H_
|
||||
#define _IOCTL_COMMON_NVSWITCH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define NVSWITCH_DEV_IO_TYPE 'd'
|
||||
#define NVSWITCH_CTL_IO_TYPE 'c'
|
||||
|
||||
/*
|
||||
* Defines for IOCTL Hints
|
||||
*
|
||||
* NVSWITCH_IO_READ_ONLY :
|
||||
* Only reads parameters from the kernel and does not pass any to it
|
||||
*
|
||||
* NVSWITCH_IO_WRITE_ONLY :
|
||||
* Only writes parameters to the kernel, but does not want anything back.
|
||||
*
|
||||
* NVSWITCH_IO_WRITE_READ :
|
||||
* Writes data to the kernel and wants information back
|
||||
*
|
||||
* NVSWITCH_IO_DEFAULT :
|
||||
* Don't copy anything into the kernel, nor copy anything back.
|
||||
*/
|
||||
#define NVSWITCH_IO_READ_ONLY 0x0
|
||||
#define NVSWITCH_IO_WRITE_ONLY 0x1
|
||||
#define NVSWITCH_IO_WRITE_READ 0x2
|
||||
#define NVSWITCH_IO_DEFAULT 0x3
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64))
|
||||
/*
|
||||
* Values of less than 0x800 are reserved for Microsoft.
|
||||
* Values of 0x800 and higher can be used by vendors.
|
||||
*/
|
||||
#define IOCTL_START_INDEX 0x800
|
||||
|
||||
/*
|
||||
* Macro for defining new IOCTLs in a platform independent way.
|
||||
*/
|
||||
#define NVSWITCH_IOCTL_CODE(ioType, ctrl, paramType, direction) \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_START_INDEX + ctrl, METHOD_BUFFERED, \
|
||||
(FILE_READ_DATA | FILE_WRITE_DATA))
|
||||
#else
|
||||
|
||||
/*
|
||||
* Macro for defining new IOCTLs in a platform independent way.
|
||||
*
|
||||
* Select Linux specific IOCTL defining macro (_IO, _IOR, _IOW, _IOWR)
|
||||
* based on IOCTL direction.
|
||||
*/
|
||||
#define NVSWITCH_IOCTL_CODE(ioType, ctrl, paramType, direction) \
|
||||
((direction == NVSWITCH_IO_READ_ONLY) ? _IOR(ioType, ctrl, paramType) : \
|
||||
(direction == NVSWITCH_IO_WRITE_ONLY) ? _IOW(ioType, ctrl, paramType) : \
|
||||
(direction == NVSWITCH_IO_WRITE_READ) ? _IOWR(ioType, ctrl, paramType) : \
|
||||
_IO(ioType, ctrl))
|
||||
|
||||
#endif // (defined(_WIN32) || defined(_WIN64))
|
||||
|
||||
/*
|
||||
* NVSWITCH_NVLINK_MAX_LANES is used by both internal and exteranl IOCTLs.
|
||||
*/
|
||||
#define NVSWITCH_NVLINK_MAX_LANES 4
|
||||
|
||||
/*
|
||||
* Common Fabric State enums
|
||||
*
|
||||
* Definitions:
|
||||
* Driver Fabric State is intended to reflect the state of the driver and
|
||||
* fabric manager. Once FM sets the Driver State to CONFIGURED, it is
|
||||
* expected the FM will send heartbeat updates. If the heartbeat is not
|
||||
* received before the session timeout, then the driver reports status
|
||||
* as MANAGER_TIMEOUT.
|
||||
*
|
||||
* Device Fabric State reflects the state of the nvswitch device.
|
||||
* FM sets the Device Fabric State to CONFIGURED once FM is managing the
|
||||
* device. If the Device Fabric State is BLACKLISTED then the device is
|
||||
* not available for use; opens fail for a blacklisted device, and interrupts
|
||||
* are disabled.
|
||||
*
|
||||
* Blacklist Reason provides additional detail of why a device is blacklisted.
|
||||
*/
|
||||
typedef enum nvswitch_driver_fabric_state
|
||||
{
|
||||
NVSWITCH_DRIVER_FABRIC_STATE_OFFLINE = 0, // offline (No driver loaded)
|
||||
NVSWITCH_DRIVER_FABRIC_STATE_STANDBY, // driver up, no FM
|
||||
NVSWITCH_DRIVER_FABRIC_STATE_CONFIGURED, // driver up, FM up
|
||||
NVSWITCH_DRIVER_FABRIC_STATE_MANAGER_TIMEOUT, // driver up, FM timed out
|
||||
NVSWITCH_DRIVER_FABRIC_STATE_MANAGER_ERROR, // driver up, FM in error state
|
||||
NVSWITCH_DRIVER_FABRIC_STATE_COUNT
|
||||
} NVSWITCH_DRIVER_FABRIC_STATE;
|
||||
|
||||
typedef enum nvswitch_device_fabric_state
|
||||
{
|
||||
NVSWITCH_DEVICE_FABRIC_STATE_OFFLINE = 0, // offline: No driver, no FM
|
||||
NVSWITCH_DEVICE_FABRIC_STATE_STANDBY, // driver up, no FM, not blacklisted
|
||||
NVSWITCH_DEVICE_FABRIC_STATE_CONFIGURED, // driver up, FM up, not blacklisted
|
||||
NVSWITCH_DEVICE_FABRIC_STATE_BLACKLISTED, // device is blacklisted
|
||||
NVSWITCH_DEVICE_FABRIC_STATE_COUNT
|
||||
} NVSWITCH_DEVICE_FABRIC_STATE;
|
||||
|
||||
typedef enum nvswitch_device_blacklist_mode
|
||||
{
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_NONE = 0, // device is not blacklisted
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_OUT_OF_BAND, // manually blacklisted by out-of-band client
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_IN_BAND, // manually blacklisted by in-band OS config
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_MANUAL_PEER, // FM indicates blacklisted due to peer manual blacklisted
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_TRUNK_LINK_FAILURE, // FM indicates blacklisted due to trunk link failure
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_TRUNK_LINK_FAILURE_PEER, // FM indicates blacklisted due to trunk link failure of peer
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_ACCESS_LINK_FAILURE, // FM indicates blacklisted due to access link failure
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_ACCESS_LINK_FAILURE_PEER, // FM indicates blacklisted due to access link failure of peer
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_UNSPEC_DEVICE_FAILURE, // FM indicates blacklisted due to unspecified device failure
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON_UNSPEC_DEVICE_FAILURE_PEER // FM indicates blacklisted due to unspec device failure of peer
|
||||
} NVSWITCH_DEVICE_BLACKLIST_REASON;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif //_IOCTL_COMMON_NVSWITCH_H_
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _IOCTL_NVSWITCH_H_
|
||||
#define _IOCTL_NVSWITCH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ioctl_common_nvswitch.h"
|
||||
#include "nvCpuUuid.h"
|
||||
|
||||
/* 4 chars for "SWX-" prefix + 36 chars for UUID string + 1 char for '\0' */
|
||||
#define NVSWITCH_UUID_STRING_LENGTH 41
|
||||
|
||||
#define NVSWITCH_NIBBLE_TO_CHAR(nibble) \
|
||||
(((nibble) > 9) ? (((nibble) - 10) + 'A') : ((nibble) + '0'))
|
||||
|
||||
static NV_INLINE
|
||||
NvU32 nvswitch_uuid_to_string(NvUuid *uuid, char *str, NvU32 strLen)
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
|
||||
if ((uuid == NULL) || (str == NULL) || (strLen < NVSWITCH_UUID_STRING_LENGTH))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
str[j++] = 'S';
|
||||
str[j++] = 'W';
|
||||
str[j++] = 'X';
|
||||
str[j++] = '-';
|
||||
|
||||
for (i = 0; i < NV_UUID_LEN; i++)
|
||||
{
|
||||
if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
|
||||
{
|
||||
str[j++] = '-';
|
||||
}
|
||||
|
||||
str[j++] = NVSWITCH_NIBBLE_TO_CHAR((uuid->uuid[i] & 0xF0) >> 4);
|
||||
str[j++] = NVSWITCH_NIBBLE_TO_CHAR(uuid->uuid[i] & 0x0F);
|
||||
}
|
||||
|
||||
str[j++] = '\0';
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/*
|
||||
* This file defines IOCTL calls that work with nvidia-nvswitchctl
|
||||
* (device agnostic) node.
|
||||
*/
|
||||
|
||||
#define NVSWITCH_VERSION_STRING_LENGTH 64
|
||||
|
||||
/*
|
||||
* Version string
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char version[NVSWITCH_VERSION_STRING_LENGTH];
|
||||
} NVSWITCH_VERSION;
|
||||
|
||||
/*
|
||||
* NVSWITCH_CTL_CHECK_VERSION
|
||||
*
|
||||
* The interface will check if the client's version is supported by the driver.
|
||||
*
|
||||
* Parameters:
|
||||
* user[in]
|
||||
* Version of the interface that the client is compiled with.
|
||||
* kernel[out]
|
||||
* Version of the interface that the kernel driver is compiled with.
|
||||
* is_compatible[out]
|
||||
* Set to true, if user and kernel version are compatible.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NVSWITCH_VERSION user;
|
||||
NVSWITCH_VERSION kernel;
|
||||
NvBool is_compatible;
|
||||
} NVSWITCH_CHECK_VERSION_PARAMS;
|
||||
|
||||
/*
|
||||
* Max devices supported by the driver
|
||||
*
|
||||
* See ctrl_dev_nvswitch.h for preprocessor definition modification guidelines.
|
||||
*/
|
||||
#define NVSWITCH_MAX_DEVICES 64
|
||||
|
||||
/*
|
||||
* NVSWITCH_CTL_GET_DEVICES
|
||||
*
|
||||
* This control call will be removed soon. Use NVSWITCH_CTL_GET_DEVICES_V2 instead.
|
||||
*
|
||||
* Provides information about registered NvSwitch devices.
|
||||
*
|
||||
* Parameters:
|
||||
* deviceInstance[out]
|
||||
* Device instance of the device. This is same as the device minor number
|
||||
* for Linux platforms.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NvU32 deviceInstance;
|
||||
NvU32 pciDomain;
|
||||
NvU32 pciBus;
|
||||
NvU32 pciDevice;
|
||||
NvU32 pciFunction;
|
||||
/* See ctrl_dev_nvswitch.h for struct definition modification guidelines */
|
||||
} NVSWITCH_DEVICE_INSTANCE_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU32 deviceCount;
|
||||
NVSWITCH_DEVICE_INSTANCE_INFO info[NVSWITCH_MAX_DEVICES];
|
||||
/* See ctrl_dev_nvswitch.h for struct definition modification guidelines */
|
||||
} NVSWITCH_GET_DEVICES_PARAMS;
|
||||
|
||||
/*
|
||||
* NVSWITCH_CTL_GET_DEVICES_V2
|
||||
*
|
||||
* Provides information about registered NvSwitch devices.
|
||||
* V2 adds a UUID field to the device instance info struct
|
||||
*
|
||||
* Parameters:
|
||||
* deviceInstance[out]
|
||||
* Device instance of the device. This is same as the device minor number
|
||||
* for Linux platforms.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NvU32 deviceInstance;
|
||||
NvUuid uuid;
|
||||
NvU32 pciDomain;
|
||||
NvU32 pciBus;
|
||||
NvU32 pciDevice;
|
||||
NvU32 pciFunction;
|
||||
NVSWITCH_DRIVER_FABRIC_STATE driverState;
|
||||
NVSWITCH_DEVICE_FABRIC_STATE deviceState;
|
||||
NVSWITCH_DEVICE_BLACKLIST_REASON deviceReason;
|
||||
NvU32 physId;
|
||||
|
||||
/* See ctrl_dev_nvswitch.h for struct definition modification guidelines */
|
||||
} NVSWITCH_DEVICE_INSTANCE_INFO_V2;
|
||||
|
||||
#define NVSWITCH_INVALID_PHYS_ID NV_U32_MAX
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU32 deviceCount;
|
||||
NVSWITCH_DEVICE_INSTANCE_INFO_V2 info[NVSWITCH_MAX_DEVICES];
|
||||
/* See ctrl_dev_nvswitch.h for struct definition modification guidelines */
|
||||
} NVSWITCH_GET_DEVICES_V2_PARAMS;
|
||||
|
||||
#define NVSWITCH_DEVICE_NAME_STRING_LENGTH 10
|
||||
|
||||
/*
|
||||
* CTRL_NVSWITCH_GET_DEVICE_NODES
|
||||
*
|
||||
* Provides a mapping of the VMWare kernel device names (vmfgx[N]) and registered
|
||||
* NVSwitch devices (nvidia-nvswitch[N]).
|
||||
*
|
||||
* This IOCTL is only implemented for VMWare.
|
||||
*
|
||||
* Parameters:
|
||||
* deviceInstance[out]
|
||||
* Device instance of the device. This is same as the device minor number
|
||||
* for VMWare platforms.
|
||||
* dev_name[out]
|
||||
* VMWare kernel device name of the nvswitch device (vmfgx[N])
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NvU32 deviceInstance;
|
||||
NvUuid uuid;
|
||||
NvU8 dev_name[NVSWITCH_DEVICE_NAME_STRING_LENGTH];
|
||||
/* See ctrl_dev_nvswitch.h for struct definition modification guidelines */
|
||||
} NVSWITCH_DEVICE_NODE_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU32 deviceCount;
|
||||
NVSWITCH_DEVICE_NODE_INFO info[NVSWITCH_MAX_DEVICES];
|
||||
/* See ctrl_dev_nvswitch.h for struct definition modification guidelines */
|
||||
} NVSWITCH_GET_DEVICE_NODES_PARAMS;
|
||||
|
||||
#define CTRL_NVSWITCH_GET_DEVICES 0x01
|
||||
#define CTRL_NVSWITCH_CHECK_VERSION 0x02
|
||||
#define CTRL_NVSWITCH_GET_DEVICES_V2 0x03
|
||||
#define CTRL_NVSWITCH_GET_DEVICE_NODES 0x04
|
||||
|
||||
/*
|
||||
* Nvswitchctl (device agnostic) IOCTLs
|
||||
*/
|
||||
|
||||
#define IOCTL_NVSWITCH_GET_DEVICES \
|
||||
NVSWITCH_IOCTL_CODE(NVSWITCH_CTL_IO_TYPE, CTRL_NVSWITCH_GET_DEVICES, NVSWITCH_GET_DEVICES_PARAMS, \
|
||||
NVSWITCH_IO_READ_ONLY)
|
||||
#define IOCTL_NVSWITCH_CHECK_VERSION \
|
||||
NVSWITCH_IOCTL_CODE(NVSWITCH_CTL_IO_TYPE, CTRL_NVSWITCH_CHECK_VERSION, NVSWITCH_CHECK_VERSION_PARAMS, \
|
||||
NVSWITCH_IO_WRITE_READ)
|
||||
#define IOCTL_NVSWITCH_GET_DEVICES_V2 \
|
||||
NVSWITCH_IOCTL_CODE(NVSWITCH_CTL_IO_TYPE, CTRL_NVSWITCH_GET_DEVICES_V2, NVSWITCH_GET_DEVICES_V2_PARAMS, \
|
||||
NVSWITCH_IO_READ_ONLY)
|
||||
#define IOCTL_NVSWITCH_GET_DEVICE_NODES \
|
||||
NVSWITCH_IOCTL_CODE(NVSWITCH_CTL_IO_TYPE, CTRL_NVSWITCH_GET_DEVICE_NODES, NVSWITCH_GET_DEVICE_NODES_PARAMS, \
|
||||
NVSWITCH_IO_READ_ONLY)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_IOCTL_NVSWITCH_H_
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
/** @file
|
||||
* Defines base cryptographic library APIs.
|
||||
* The Base Cryptographic Library provides implementations of basic cryptography
|
||||
* primitives (hash Serials, HMAC, AES, RSA, Diffie-Hellman, Elliptic Curve, etc) for security
|
||||
* functionality enabling.
|
||||
**/
|
||||
|
||||
#ifndef CRYPTLIB_H
|
||||
#define CRYPTLIB_H
|
||||
|
||||
#include "internal/libspdm_lib_config.h"
|
||||
|
||||
#define LIBSPDM_CRYPTO_NID_NULL 0x0000
|
||||
|
||||
/* Hash */
|
||||
#define LIBSPDM_CRYPTO_NID_SHA256 0x0001
|
||||
#define LIBSPDM_CRYPTO_NID_SHA384 0x0002
|
||||
#define LIBSPDM_CRYPTO_NID_SHA512 0x0003
|
||||
#define LIBSPDM_CRYPTO_NID_SHA3_256 0x0004
|
||||
#define LIBSPDM_CRYPTO_NID_SHA3_384 0x0005
|
||||
#define LIBSPDM_CRYPTO_NID_SHA3_512 0x0006
|
||||
#define LIBSPDM_CRYPTO_NID_SM3_256 0x0007
|
||||
|
||||
/* Signing */
|
||||
#define LIBSPDM_CRYPTO_NID_RSASSA2048 0x0101
|
||||
#define LIBSPDM_CRYPTO_NID_RSASSA3072 0x0102
|
||||
#define LIBSPDM_CRYPTO_NID_RSASSA4096 0x0103
|
||||
#define LIBSPDM_CRYPTO_NID_RSAPSS2048 0x0104
|
||||
#define LIBSPDM_CRYPTO_NID_RSAPSS3072 0x0105
|
||||
#define LIBSPDM_CRYPTO_NID_RSAPSS4096 0x0106
|
||||
#define LIBSPDM_CRYPTO_NID_ECDSA_NIST_P256 0x0107
|
||||
#define LIBSPDM_CRYPTO_NID_ECDSA_NIST_P384 0x0108
|
||||
#define LIBSPDM_CRYPTO_NID_ECDSA_NIST_P521 0x0109
|
||||
#define LIBSPDM_CRYPTO_NID_SM2_DSA_P256 0x010A
|
||||
#define LIBSPDM_CRYPTO_NID_EDDSA_ED25519 0x010B
|
||||
#define LIBSPDM_CRYPTO_NID_EDDSA_ED448 0x010C
|
||||
|
||||
/* Key Exchange */
|
||||
#define LIBSPDM_CRYPTO_NID_FFDHE2048 0x0201
|
||||
#define LIBSPDM_CRYPTO_NID_FFDHE3072 0x0202
|
||||
#define LIBSPDM_CRYPTO_NID_FFDHE4096 0x0203
|
||||
#define LIBSPDM_CRYPTO_NID_SECP256R1 0x0204
|
||||
#define LIBSPDM_CRYPTO_NID_SECP384R1 0x0205
|
||||
#define LIBSPDM_CRYPTO_NID_SECP521R1 0x0206
|
||||
#define LIBSPDM_CRYPTO_NID_SM2_KEY_EXCHANGE_P256 0x0207
|
||||
#define LIBSPDM_CRYPTO_NID_CURVE_X25519 0x0208
|
||||
#define LIBSPDM_CRYPTO_NID_CURVE_X448 0x0209
|
||||
|
||||
/* AEAD */
|
||||
#define LIBSPDM_CRYPTO_NID_AES_128_GCM 0x0301
|
||||
#define LIBSPDM_CRYPTO_NID_AES_256_GCM 0x0302
|
||||
#define LIBSPDM_CRYPTO_NID_CHACHA20_POLY1305 0x0303
|
||||
#define LIBSPDM_CRYPTO_NID_SM4_128_GCM 0x0304
|
||||
|
||||
/* X.509 v3 key usage extension flags. */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_DIGITAL_SIGNATURE 0x80 /* bit 0 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_NON_REPUDIATION 0x40 /* bit 1 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_KEY_ENCIPHERMENT 0x20 /* bit 2 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_DATA_ENCIPHERMENT 0x10 /* bit 3 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_KEY_AGREEMENT 0x08 /* bit 4 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_KEY_CERT_SIGN 0x04 /* bit 5 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_CRL_SIGN 0x02 /* bit 6 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_ENCIPHER_ONLY 0x01 /* bit 7 */
|
||||
#define LIBSPDM_CRYPTO_X509_KU_DECIPHER_ONLY 0x8000 /* bit 8 */
|
||||
|
||||
/* These constants comply with the DER encoded ASN.1 type tags. */
|
||||
#define LIBSPDM_CRYPTO_ASN1_BOOLEAN 0x01
|
||||
#define LIBSPDM_CRYPTO_ASN1_INTEGER 0x02
|
||||
#define LIBSPDM_CRYPTO_ASN1_BIT_STRING 0x03
|
||||
#define LIBSPDM_CRYPTO_ASN1_OCTET_STRING 0x04
|
||||
#define LIBSPDM_CRYPTO_ASN1_NULL 0x05
|
||||
#define LIBSPDM_CRYPTO_ASN1_OID 0x06
|
||||
#define LIBSPDM_CRYPTO_ASN1_UTF8_STRING 0x0C
|
||||
#define LIBSPDM_CRYPTO_ASN1_SEQUENCE 0x10
|
||||
#define LIBSPDM_CRYPTO_ASN1_SET 0x11
|
||||
#define LIBSPDM_CRYPTO_ASN1_PRINTABLE_STRING 0x13
|
||||
#define LIBSPDM_CRYPTO_ASN1_T61_STRING 0x14
|
||||
#define LIBSPDM_CRYPTO_ASN1_IA5_STRING 0x16
|
||||
#define LIBSPDM_CRYPTO_ASN1_UTC_TIME 0x17
|
||||
#define LIBSPDM_CRYPTO_ASN1_GENERALIZED_TIME 0x18
|
||||
#define LIBSPDM_CRYPTO_ASN1_UNIVERSAL_STRING 0x1C
|
||||
#define LIBSPDM_CRYPTO_ASN1_BMP_STRING 0x1E
|
||||
#define LIBSPDM_CRYPTO_ASN1_PRIMITIVE 0x00
|
||||
#define LIBSPDM_CRYPTO_ASN1_CONSTRUCTED 0x20
|
||||
#define LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC 0x80
|
||||
|
||||
#define LIBSPDM_CRYPTO_ASN1_TAG_CLASS_MASK 0xC0
|
||||
#define LIBSPDM_CRYPTO_ASN1_TAG_PC_MASK 0x20
|
||||
#define LIBSPDM_CRYPTO_ASN1_TAG_VALUE_MASK 0x1F
|
||||
|
||||
#include "hal/library/cryptlib/cryptlib_hash.h"
|
||||
#include "hal/library/cryptlib/cryptlib_mac.h"
|
||||
#include "hal/library/cryptlib/cryptlib_aead.h"
|
||||
#include "hal/library/cryptlib/cryptlib_cert.h"
|
||||
#include "hal/library/cryptlib/cryptlib_hkdf.h"
|
||||
#include "hal/library/cryptlib/cryptlib_rsa.h"
|
||||
#include "hal/library/cryptlib/cryptlib_ec.h"
|
||||
#include "hal/library/cryptlib/cryptlib_dh.h"
|
||||
#include "hal/library/cryptlib/cryptlib_ecd.h"
|
||||
#include "hal/library/cryptlib/cryptlib_sm2.h"
|
||||
#include "hal/library/cryptlib/cryptlib_rng.h"
|
||||
|
||||
#endif /* CRYPTLIB_H */
|
||||
@@ -0,0 +1,415 @@
|
||||
/**
|
||||
* Copyright Notice:
|
||||
* Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
**/
|
||||
|
||||
#ifndef SPDM_LIB_CONFIG_H
|
||||
#define SPDM_LIB_CONFIG_H
|
||||
|
||||
/* Enables assertions and debug printing. When `LIBSPDM_DEBUG_ENABLE` is defined it overrides or
|
||||
* sets the values of `LIBSPDM_DEBUG_PRINT_ENABLE`, `LIBSPDM_DEBUG_ASSERT_ENABLE`, and
|
||||
* `LIBSPDM_BLOCK_ENABLE` to the value of `LIBSPDM_DEBUG_ENABLE`.
|
||||
*
|
||||
* Note that if this file is used with CMake and `DTARGET=Release` is defined, then all debugging
|
||||
* is disabled.
|
||||
*/
|
||||
#ifndef LIBSPDM_DEBUG_ENABLE
|
||||
#define LIBSPDM_DEBUG_ENABLE 1
|
||||
#endif
|
||||
|
||||
/* The SPDM specification allows a Responder to return up to 256 version entries in the `VERSION`
|
||||
* response to the Requester, including duplicate entries. For a Requester this value specifies the
|
||||
* maximum number of entries that libspdm will tolerate in a `VERSION` response before returning an
|
||||
* error. A similiar macro, `SPDM_MAX_VERSION_COUNT`, exists for the Responder. However this macro
|
||||
* is not meant to be configured by the Integrator.
|
||||
*/
|
||||
#ifndef LIBSPDM_MAX_VERSION_COUNT
|
||||
#define LIBSPDM_MAX_VERSION_COUNT 5
|
||||
#endif
|
||||
|
||||
/* This value specifies the maximum size, in bytes, of the `PSK_EXCHANGE.RequesterContext` and,
|
||||
* if supported by the Responder, `PSK_EXCHANGE_RSP.ResponderContext` fields. The fields are
|
||||
* typically random or monotonically increasing numbers.
|
||||
*/
|
||||
#ifndef LIBSPDM_PSK_CONTEXT_LENGTH
|
||||
#define LIBSPDM_PSK_CONTEXT_LENGTH LIBSPDM_MAX_HASH_SIZE
|
||||
#endif
|
||||
/* This value specifies the maximum size, in bytes, of the `PSK_EXCHANGE.PSKHint` field.*/
|
||||
#ifndef LIBSPDM_PSK_MAX_HINT_LENGTH
|
||||
#define LIBSPDM_PSK_MAX_HINT_LENGTH 16
|
||||
#endif
|
||||
|
||||
/* libspdm allows an Integrator to specify multiple root certificates as trust anchors when
|
||||
* verifying certificate chains from an endpoint. This value specifies the maximum number of root
|
||||
* certificates that libspdm can support.
|
||||
*/
|
||||
#ifndef LIBSPDM_MAX_ROOT_CERT_SUPPORT
|
||||
#define LIBSPDM_MAX_ROOT_CERT_SUPPORT 10
|
||||
#endif
|
||||
|
||||
/* If the Responder supports it a Requester is allowed to establish multiple secure sessions with
|
||||
* the Responder. This value specifies the maximum number of sessions libspdm can support.
|
||||
*/
|
||||
#ifndef LIBSPDM_MAX_SESSION_COUNT
|
||||
#define LIBSPDM_MAX_SESSION_COUNT 4
|
||||
#endif
|
||||
/* This value specifies the maximum size, in bytes, of a certificate chain that can be stored in a
|
||||
* libspdm context.
|
||||
*/
|
||||
#ifndef LIBSPDM_MAX_CERT_CHAIN_SIZE
|
||||
#define LIBSPDM_MAX_CERT_CHAIN_SIZE 0x1000
|
||||
#endif
|
||||
#ifndef LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE
|
||||
#define LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE 0x1000
|
||||
#endif
|
||||
/* Partial certificates can be retrieved from a Requester or Responder and through multiple messages
|
||||
* the complete certificate chain can be constructed. This value specifies the maximum size,
|
||||
* in bytes, of a partial certificate that can be sent or received.
|
||||
*/
|
||||
#ifndef LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN
|
||||
#define LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN 1024
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_MAX_MESSAGE_BUFFER_SIZE
|
||||
#define LIBSPDM_MAX_MESSAGE_BUFFER_SIZE 0x1200
|
||||
#endif
|
||||
#ifndef LIBSPDM_MAX_MESSAGE_SMALL_BUFFER_SIZE
|
||||
#define LIBSPDM_MAX_MESSAGE_SMALL_BUFFER_SIZE 0x100 /* to hold message_a before negotiate*/
|
||||
#endif
|
||||
#ifndef LIBSPDM_MAX_MESSAGE_MEDIUM_BUFFER_SIZE
|
||||
#define LIBSPDM_MAX_MESSAGE_MEDIUM_BUFFER_SIZE 0x300 /* to hold message_k before finished_key is ready*/
|
||||
#endif
|
||||
|
||||
/* If the Responder replies with a Busy `ERROR` response to a request then the Requester is free to
|
||||
* retry sending the request. This value specifies the maximum number of times libspdm will retry
|
||||
* sending the request before returning an error. If its value is 0 then libspdm will not send any
|
||||
* retry requests.
|
||||
*/
|
||||
#ifndef LIBSPDM_MAX_REQUEST_RETRY_TIMES
|
||||
#define LIBSPDM_MAX_REQUEST_RETRY_TIMES 3
|
||||
#endif
|
||||
#ifndef LIBSPDM_MAX_SESSION_STATE_CALLBACK_NUM
|
||||
#define LIBSPDM_MAX_SESSION_STATE_CALLBACK_NUM 4
|
||||
#endif
|
||||
#ifndef LIBSPDM_MAX_CONNECTION_STATE_CALLBACK_NUM
|
||||
#define LIBSPDM_MAX_CONNECTION_STATE_CALLBACK_NUM 4
|
||||
#endif
|
||||
#ifndef LIBSPDM_MAX_KEY_UPDATE_CALLBACK_NUM
|
||||
#define LIBSPDM_MAX_KEY_UPDATE_CALLBACK_NUM 4
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_MAX_CSR_SIZE
|
||||
#define LIBSPDM_MAX_CSR_SIZE 0x1000
|
||||
#endif
|
||||
|
||||
/* To ensure integrity in communication between the Requester and the Responder libspdm calculates
|
||||
* cryptographic digests and signatures over multiple requests and responses. This value specifies
|
||||
* whether libspdm will use a running calculation over the transcript, where requests and responses
|
||||
* are discarded as they are cryptographically consumed, or whether libspdm will buffer the entire
|
||||
* transcript before calculating the digest or signature.
|
||||
*/
|
||||
#ifndef LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
|
||||
#define LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Cryptography Configuration
|
||||
* In each category, at least one should be selected.
|
||||
* NOTE: Not all combination can be supported. E.g. Don't mix NIST algo with SMx.*/
|
||||
|
||||
#ifndef LIBSPDM_RSA_SSA_SUPPORT
|
||||
#define LIBSPDM_RSA_SSA_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_RSA_PSS_SUPPORT
|
||||
#define LIBSPDM_RSA_PSS_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_ECDSA_SUPPORT
|
||||
#define LIBSPDM_ECDSA_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SM2_DSA_SUPPORT
|
||||
#define LIBSPDM_SM2_DSA_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_EDDSA_ED25519_SUPPORT
|
||||
#define LIBSPDM_EDDSA_ED25519_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_EDDSA_ED448_SUPPORT
|
||||
#define LIBSPDM_EDDSA_ED448_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_FFDHE_SUPPORT
|
||||
#define LIBSPDM_FFDHE_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_ECDHE_SUPPORT
|
||||
#define LIBSPDM_ECDHE_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SM2_KEY_EXCHANGE_SUPPORT
|
||||
#define LIBSPDM_SM2_KEY_EXCHANGE_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_AEAD_GCM_SUPPORT
|
||||
#define LIBSPDM_AEAD_GCM_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT
|
||||
#define LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_AEAD_SM4_SUPPORT
|
||||
#define LIBSPDM_AEAD_SM4_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_SHA256_SUPPORT
|
||||
#define LIBSPDM_SHA256_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SHA384_SUPPORT
|
||||
#define LIBSPDM_SHA384_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SHA512_SUPPORT
|
||||
#define LIBSPDM_SHA512_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SHA3_256_SUPPORT
|
||||
#define LIBSPDM_SHA3_256_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SHA3_384_SUPPORT
|
||||
#define LIBSPDM_SHA3_384_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SHA3_512_SUPPORT
|
||||
#define LIBSPDM_SHA3_512_SUPPORT 1
|
||||
#endif
|
||||
#ifndef LIBSPDM_SM3_256_SUPPORT
|
||||
#define LIBSPDM_SM3_256_SUPPORT 1
|
||||
#endif
|
||||
|
||||
/* Code space optimization for Optional request/response messages.*/
|
||||
|
||||
/* Consumers of libspdm may wish to not fully implement all of the optional
|
||||
* SPDM request/response messages. Therefore we have provided these
|
||||
* SPDM_ENABLE_CAPABILITY_***_CAP compile time switches as an optimization
|
||||
* disable the code (#if 0) related to said optional capability, thereby
|
||||
* reducing the code space used in the image.*/
|
||||
|
||||
/* A single switch may enable/disable a single capability or group of related
|
||||
* capabilities.*/
|
||||
|
||||
/* LIBSPDM_ENABLE_CAPABILITY_CERT_CAP - Enable/Disable single CERT capability.
|
||||
* LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP - Enable/Disable single CHAL capability.
|
||||
* LIBSPDM_ENABLE_CAPABILTIY_MEAS_CAP - Enable/Disables multiple MEAS capabilities:
|
||||
* (MEAS_CAP_NO_SIG, MEAS_CAP_SIG, MEAS_FRESH_CAP)*/
|
||||
|
||||
/* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP - Enable/Disable single Key Exchange capability.
|
||||
* LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP - Enable/Disable PSK_EX and PSK_FINISH.*/
|
||||
|
||||
/* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP - Enable/Disable mutual authentication.
|
||||
* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP - Enable/Disable encapsulated message.*/
|
||||
|
||||
/* LIBSPDM_ENABLE_CAPABILITY_GET_CSR_CAP - Enable/Disable get csr capability.
|
||||
* LIBSPDM_ENABLE_CAPABILITY_SET_CERTIFICATE_CAP - Enable/Disable set certificate capability. */
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_CERT_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_CERT_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_GET_CSR_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_GET_CSR_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_SET_CERTIFICATE_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_SET_CERTIFICATE_CAP 1
|
||||
#endif
|
||||
|
||||
#ifndef LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
|
||||
#define LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MinDataTransferSize = 42
|
||||
*
|
||||
* H = HashLen = HmacLen = [32, 64]
|
||||
* S = SigLen = [64, 512]
|
||||
* D = ExchangeDataLen = [64, 512]
|
||||
* R = RequesterContextLen >= 32
|
||||
* R = ResponderContextLen >= 0
|
||||
* O = OpaqueDataLen <= 1024
|
||||
*
|
||||
* Max Chunk No = 1, if (message size <= 42)
|
||||
* Max Chunk No = [(message size + 4) / 30] roundup, if (message size > 42)
|
||||
*
|
||||
* +==========================+==========================================+=========+
|
||||
* | Command | Size |MaxChunk |
|
||||
* +==========================+==========================================+=========+
|
||||
* | GET_VERSION | 4 | 1 |
|
||||
* | VERSION {1.0, 1.1, 1.2} | 6 + 2 * 3 = 12 | 1 |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | GET_CAPABILITIES 1.2 | 20 | 1 |
|
||||
* | CAPABILITIES 1.2 | 20 | 1 |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | ERROR | 4 | 1 |
|
||||
* | ERROR(ResponseTooLarge) | 4 + 4 = 8 | 1 |
|
||||
* | ERROR(LargeResponse) | 4 + 1 = 5 | 1 |
|
||||
* | ERROR(ResponseNotReady) | 4 + 4 = 8 | 1 |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | CHUNK_SEND header | 12 + L0 (0 or 4) | 1 |
|
||||
* | CHUNK_RESPONSE header | 12 + L0 (0 or 4) | 1 |
|
||||
* +==========================+==========================================+=========+
|
||||
* | NEGOTIATE_ALGORITHMS 1.2 | 32 + 4 * 4 = 48 | 2 |
|
||||
* | ALGORITHMS 1.2 | 36 + 4 * 4 = 52 | 2 |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | GET_DIGESTS 1.2 | 4 | 1 |
|
||||
* | DIGESTS 1.2 | 4 + H * SlotNum = [36, 516] | [1, 18] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | GET_CERTIFICATE 1.2 | 8 | 1 |
|
||||
* | CERTIFICATE 1.2 | 8 + PortionLen | [1, ] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | CHALLENGE 1.2 | 40 | 1 |
|
||||
* | CHALLENGE_AUTH 1.2 | 38 + H * 2 + S [+ O] = [166, 678] | [6, 23] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | GET_MEASUREMENTS 1.2 | 5 + Nounce (0 or 32) | 1 |
|
||||
* | MEASUREMENTS 1.2 | 42 + MeasRecLen (+ S) [+ O] = [106, 554] | [4, 19] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | KEY_EXCHANGE 1.2 | 42 + D [+ O] = [106, 554] | [4, 19] |
|
||||
* | KEY_EXCHANGE_RSP 1.2 | 42 + D + H + S (+ H) [+ O] = [234, 1194] | [8, 40] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | FINISH 1.2 | 4 (+ S) + H = [100, 580] | [4, 20] |
|
||||
* | FINISH_RSP 1.2 | 4 (+ H) = [36, 69] | [1, 3] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | PSK_EXCHANGE 1.2 | 12 [+ PSKHint] + R [+ O] = 44 | 2 |
|
||||
* | PSK_EXCHANGE_RSP 1.2 | 12 + R + H (+ H) [+ O] = [108, 172] | [4, 6] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | PSK_FINISH 1.2 | 4 + H = [36, 68] | [1, 3] |
|
||||
* | PSK_FINISH_RSP 1.2 | 4 | 1 |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | GET_CSR 1.2 | 8 + RequesterInfoLen [+ O] | [1, ] |
|
||||
* | CSR 1.2 | 8 + CSRLength | [1, ] |
|
||||
* +--------------------------+------------------------------------------+---------+
|
||||
* | SET_CERTIFICATE 1.2 | 4 + CertChainLen | [1, ] |
|
||||
* | SET_CERTIFICATE_RSP 1.2 | 4 | 1 |
|
||||
* +==========================+==========================================+=========+
|
||||
*/
|
||||
|
||||
/* Maximum size of a large SPDM message.
|
||||
* If chunk is unsupported, it must be same as LIBSPDM_DATA_TRANSFER_SIZE.
|
||||
* If chunk is supported, it must be larger than LIBSPDM_DATA_TRANSFER_SIZE.
|
||||
* It matches MaxSPDMmsgSize in SPDM specification. */
|
||||
#ifndef LIBSPDM_MAX_SPDM_MSG_SIZE
|
||||
#define LIBSPDM_MAX_SPDM_MSG_SIZE LIBSPDM_MAX_MESSAGE_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
/* Maximum size of a single SPDM message.
|
||||
* It matches DataTransferSize in SPDM specification. */
|
||||
#ifndef LIBSPDM_DATA_TRANSFER_SIZE
|
||||
#define LIBSPDM_DATA_TRANSFER_SIZE LIBSPDM_MAX_MESSAGE_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
/* Required sender/receive buffer in device io.
|
||||
* NOTE: This is transport specific. Below configuration is just an example.
|
||||
* +-------+--------+---------------------------+------+--+------+---+--------+-----+
|
||||
* | TYPE |TransHdr| EncryptionHeader |AppHdr| |Random|MAC|AlignPad|FINAL|
|
||||
* | | |SessionId|SeqNum|Len|AppLen| | | | | | |
|
||||
* +-------+--------+---------------------------+------+ +------+---+--------+-----+
|
||||
* | MCTP | 1 | 4 | 2 | 2 | 2 | 1 | | 32 | 12| 0 | 56 |
|
||||
* |PCI_DOE| 8 | 4 | 0 | 2 | 2 | 0 | | 0 | 12| 3 | 31 |
|
||||
* +-------+--------+---------------------------+------+--+------+---+--------+-----+
|
||||
*/
|
||||
#ifndef LIBSPDM_TRANSPORT_ADDITIONAL_SIZE
|
||||
#define LIBSPDM_TRANSPORT_ADDITIONAL_SIZE 64
|
||||
#endif
|
||||
#ifndef LIBSPDM_SENDER_RECEIVE_BUFFER_SIZE
|
||||
#define LIBSPDM_SENDER_RECEIVE_BUFFER_SIZE (LIBSPDM_DATA_TRANSFER_SIZE + \
|
||||
LIBSPDM_TRANSPORT_ADDITIONAL_SIZE)
|
||||
#endif
|
||||
|
||||
|
||||
/* Required scratch buffer size for libspdm internal usage.
|
||||
* It may be used to hold the encrypted/decrypted message and/or last sent/received message.
|
||||
* It may be used to hold the large request/response and intermediate send/receive buffer
|
||||
* in case of chunking.
|
||||
*
|
||||
* If chunking is not supported, it may be just LIBSPDM_SENDER_RECEIVE_BUFFER_SIZE.
|
||||
* If chunking is supported, it should be at least below.
|
||||
*
|
||||
* +---------------+--------------+--------------------------+------------------------------+
|
||||
* |SECURE_MESSAGE |LARGE_MESSAGE | SENDER_RECEIVER | LARGE_SENDER_RECEIVER |
|
||||
* +---------------+--------------+--------------------------+------------------------------+
|
||||
* |<-Secure msg ->|<-Large msg ->|<-Snd/Rcv buf for chunk ->|<-Snd/Rcv buf for large msg ->|
|
||||
*
|
||||
* The value is NOT configurable.
|
||||
* The value MAY be changed in different libspdm version.
|
||||
* It is exposed here, just in case the libspdm consumer wants to configure the setting at build time.
|
||||
*/
|
||||
#if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
|
||||
|
||||
/* first section */
|
||||
#define LIBSPDM_SCRATCH_BUFFER_SECURE_MESSAGE_OFFSET 0
|
||||
|
||||
#define LIBSPDM_SCRATCH_BUFFER_SECURE_MESSAGE_CAPACITY (LIBSPDM_MAX_SPDM_MSG_SIZE)
|
||||
|
||||
/* second section */
|
||||
#define LIBSPDM_SCRATCH_BUFFER_LARGE_MESSAGE_OFFSET (LIBSPDM_SCRATCH_BUFFER_SECURE_MESSAGE_CAPACITY)
|
||||
|
||||
#define LIBSPDM_SCRATCH_BUFFER_LARGE_MESSAGE_CAPACITY (LIBSPDM_MAX_SPDM_MSG_SIZE)
|
||||
|
||||
/* third section */
|
||||
#define LIBSPDM_SCRATCH_BUFFER_SENDER_RECEIVER_OFFSET \
|
||||
(LIBSPDM_SCRATCH_BUFFER_SECURE_MESSAGE_CAPACITY + \
|
||||
LIBSPDM_SCRATCH_BUFFER_LARGE_MESSAGE_CAPACITY)
|
||||
|
||||
#define LIBSPDM_SCRATCH_BUFFER_SENDER_RECEIVER_CAPACITY (LIBSPDM_MAX_SPDM_MSG_SIZE)
|
||||
|
||||
/* fourth section */
|
||||
#define LIBSPDM_SCRATCH_BUFFER_LARGE_SENDER_RECEIVER_OFFSET \
|
||||
(LIBSPDM_SCRATCH_BUFFER_SECURE_MESSAGE_CAPACITY + \
|
||||
LIBSPDM_SCRATCH_BUFFER_LARGE_MESSAGE_CAPACITY + \
|
||||
LIBSPDM_SCRATCH_BUFFER_SENDER_RECEIVER_CAPACITY)
|
||||
|
||||
#define LIBSPDM_SCRATCH_BUFFER_LARGE_SENDER_RECEIVER_CAPACITY (LIBSPDM_MAX_SPDM_MSG_SIZE)
|
||||
|
||||
#define LIBSPDM_SCRATCH_BUFFER_SIZE (LIBSPDM_SCRATCH_BUFFER_SECURE_MESSAGE_CAPACITY + \
|
||||
LIBSPDM_SCRATCH_BUFFER_LARGE_MESSAGE_CAPACITY + \
|
||||
LIBSPDM_SCRATCH_BUFFER_SENDER_RECEIVER_CAPACITY + \
|
||||
LIBSPDM_SCRATCH_BUFFER_LARGE_SENDER_RECEIVER_CAPACITY \
|
||||
)
|
||||
|
||||
#else
|
||||
#define LIBSPDM_SCRATCH_BUFFER_SIZE (LIBSPDM_SENDER_RECEIVE_BUFFER_SIZE)
|
||||
#endif
|
||||
|
||||
/* Enable message logging.
|
||||
* See https://github.com/DMTF/libspdm/blob/main/doc/user_guide.md#message-logging
|
||||
* for more information */
|
||||
#ifndef LIBSPDM_ENABLE_MSG_LOG
|
||||
#define LIBSPDM_ENABLE_MSG_LOG 1
|
||||
#endif
|
||||
|
||||
/* Enable macro checking during compilation. */
|
||||
#ifndef LIBSPDM_CHECK_MACRO
|
||||
#define LIBSPDM_CHECK_MACRO 0
|
||||
#endif
|
||||
|
||||
#endif /* SPDM_LIB_CONFIG_H */
|
||||
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
#include "nvspdm_cryptlib_extensions.h"
|
||||
|
||||
#ifdef USE_LKCA
|
||||
#define BUFFER_SIZE (2 * 1024 * 1024)
|
||||
#define AUTH_TAG_SIZE 16
|
||||
struct lkca_aead_ctx
|
||||
{
|
||||
struct crypto_aead *aead;
|
||||
struct aead_request *req;
|
||||
char *a_data_buffer;
|
||||
char *in_buffer;
|
||||
char *out_buffer;
|
||||
char tag[AUTH_TAG_SIZE];
|
||||
};
|
||||
#endif
|
||||
|
||||
int libspdm_aead_prealloc(void **context, char const *alg)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return -ENODEV;
|
||||
#else
|
||||
struct lkca_aead_ctx *ctx;
|
||||
|
||||
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (ctx == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->aead = crypto_alloc_aead(alg, CRYPTO_ALG_TYPE_AEAD, 0);
|
||||
if (IS_ERR(ctx->aead)) {
|
||||
pr_notice("could not allocate AEAD algorithm\n");
|
||||
kfree(ctx);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ctx->req = aead_request_alloc(ctx->aead, GFP_KERNEL);
|
||||
if (ctx->req == NULL) {
|
||||
pr_info("could not allocate skcipher request\n");
|
||||
crypto_free_aead(ctx->aead);
|
||||
kfree(ctx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx->a_data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
if (ctx->a_data_buffer == NULL) {
|
||||
aead_request_free(ctx->req);
|
||||
crypto_free_aead(ctx->aead);
|
||||
kfree(ctx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx->in_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
if (ctx->in_buffer == NULL) {
|
||||
kfree(ctx->a_data_buffer);
|
||||
aead_request_free(ctx->req);
|
||||
crypto_free_aead(ctx->aead);
|
||||
kfree(ctx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx->out_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
if (ctx->out_buffer == NULL) {
|
||||
kfree(ctx->a_data_buffer);
|
||||
kfree(ctx->in_buffer);
|
||||
aead_request_free(ctx->req);
|
||||
crypto_free_aead(ctx->aead);
|
||||
kfree(ctx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*context = ctx;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void libspdm_aead_free(void *context)
|
||||
{
|
||||
#ifdef USE_LKCA
|
||||
struct lkca_aead_ctx *ctx = context;
|
||||
crypto_free_aead(ctx->aead);
|
||||
aead_request_free(ctx->req);
|
||||
kfree(ctx->a_data_buffer);
|
||||
kfree(ctx->in_buffer);
|
||||
kfree(ctx->out_buffer);
|
||||
kfree(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SG_AEAD_AAD 0
|
||||
#define SG_AEAD_TEXT 1
|
||||
#define SG_AEAD_SIG 2
|
||||
// Number of fields in AEAD scatterlist
|
||||
#define SG_AEAD_LEN 3
|
||||
|
||||
#ifdef USE_LKCA
|
||||
// This function doesn't do any allocs, it uses temp buffers instead
|
||||
static int lkca_aead_internal(struct crypto_aead *aead,
|
||||
struct aead_request *req,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
struct scatterlist sg_in[],
|
||||
struct scatterlist sg_out[],
|
||||
size_t a_data_size,
|
||||
size_t data_in_size,
|
||||
size_t *data_out_size,
|
||||
size_t tag_size,
|
||||
bool enc)
|
||||
{
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
int rc = 0;
|
||||
|
||||
if (crypto_aead_setkey(aead, key, key_size)) {
|
||||
pr_info("key could not be set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (crypto_aead_ivsize(aead) != iv_size) {
|
||||
pr_info("iv could not be set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
aead_request_set_ad(req, a_data_size);
|
||||
|
||||
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait);
|
||||
|
||||
if (enc) {
|
||||
aead_request_set_crypt(req, sg_in, sg_out, data_in_size, (u8 *) iv);
|
||||
rc = crypto_wait_req(crypto_aead_encrypt(req), &wait);
|
||||
} else {
|
||||
aead_request_set_crypt(req, sg_in, sg_out, data_in_size + tag_size, (u8 *) iv);
|
||||
rc = crypto_wait_req(crypto_aead_decrypt(req), &wait);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
pr_info("Encryption FAILED\n");
|
||||
}
|
||||
|
||||
*data_out_size = data_in_size;
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
int libspdm_aead_prealloced(void *context,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size,
|
||||
bool enc)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return -ENODEV;
|
||||
#else
|
||||
int rc = 0;
|
||||
struct scatterlist sg_in[SG_AEAD_LEN];
|
||||
struct scatterlist sg_out[SG_AEAD_LEN];
|
||||
struct lkca_aead_ctx *ctx = context;
|
||||
|
||||
|
||||
sg_init_table(sg_in, SG_AEAD_LEN);
|
||||
sg_init_table(sg_out, SG_AEAD_LEN);
|
||||
|
||||
if (!virt_addr_valid(a_data)) {
|
||||
if (a_data_size > BUFFER_SIZE) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
sg_set_buf(&sg_in[SG_AEAD_AAD], ctx->a_data_buffer, a_data_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_AAD], ctx->a_data_buffer, a_data_size);
|
||||
|
||||
memcpy(ctx->a_data_buffer, a_data, a_data_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_in[SG_AEAD_AAD], a_data, a_data_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_AAD], a_data, a_data_size);
|
||||
}
|
||||
|
||||
if (!virt_addr_valid(data_in)) {
|
||||
if (data_in_size > BUFFER_SIZE) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
sg_set_buf(&sg_in[SG_AEAD_TEXT], ctx->in_buffer, data_in_size);
|
||||
memcpy(ctx->in_buffer, data_in, data_in_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_in[SG_AEAD_TEXT], data_in, data_in_size);
|
||||
}
|
||||
|
||||
if (!virt_addr_valid(data_out)) {
|
||||
if (data_in_size > BUFFER_SIZE) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
sg_set_buf(&sg_out[SG_AEAD_TEXT], ctx->out_buffer, data_in_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_out[SG_AEAD_TEXT], data_out, data_in_size);
|
||||
}
|
||||
|
||||
// Tag is small enough that memcpy is cheaper than checking if page is virtual
|
||||
if(tag_size > AUTH_TAG_SIZE) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
sg_set_buf(&sg_in[SG_AEAD_SIG], ctx->tag, tag_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_SIG], ctx->tag, tag_size);
|
||||
|
||||
if(!enc)
|
||||
memcpy(ctx->tag, tag, tag_size);
|
||||
|
||||
rc = lkca_aead_internal(ctx->aead, ctx->req, key, key_size, iv, iv_size,
|
||||
sg_in, sg_out, a_data_size, data_in_size,
|
||||
data_out_size, tag_size, enc);
|
||||
|
||||
if (enc) {
|
||||
memcpy(tag, ctx->tag, tag_size);
|
||||
}
|
||||
|
||||
if (!virt_addr_valid(data_out)) {
|
||||
memcpy(data_out, ctx->out_buffer, data_in_size);
|
||||
}
|
||||
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
int libspdm_aead(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size,
|
||||
bool enc, char const *alg)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return -ENODEV;
|
||||
#else
|
||||
struct crypto_aead *aead = NULL;
|
||||
struct aead_request *req = NULL;
|
||||
struct scatterlist sg_in[SG_AEAD_LEN];
|
||||
struct scatterlist sg_out[SG_AEAD_LEN];
|
||||
uint8_t *a_data_shadow = NULL;
|
||||
uint8_t *data_in_shadow = NULL;
|
||||
uint8_t *data_out_shadow = NULL;
|
||||
uint8_t *tag_shadow = NULL;
|
||||
int rc = 0;
|
||||
|
||||
aead = crypto_alloc_aead(alg, CRYPTO_ALG_TYPE_AEAD, 0);
|
||||
if (IS_ERR(aead)) {
|
||||
pr_notice("could not allocate AEAD algorithm\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
req = aead_request_alloc(aead, GFP_KERNEL);
|
||||
if (req == NULL) {
|
||||
pr_info("could not allocate skcipher request\n");
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg_init_table(sg_in, SG_AEAD_LEN);
|
||||
sg_init_table(sg_out, SG_AEAD_LEN);
|
||||
|
||||
if (!virt_addr_valid(a_data)) {
|
||||
a_data_shadow = kmalloc(a_data_size, GFP_KERNEL);
|
||||
if (a_data_shadow == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg_set_buf(&sg_in[SG_AEAD_AAD], a_data_shadow, a_data_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_AAD], a_data_shadow, a_data_size);
|
||||
|
||||
memcpy(a_data_shadow, a_data, a_data_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_in[SG_AEAD_AAD], a_data, a_data_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_AAD], a_data, a_data_size);
|
||||
}
|
||||
|
||||
if (!virt_addr_valid(data_in)) {
|
||||
data_in_shadow = kmalloc(data_in_size, GFP_KERNEL);
|
||||
if (data_in_shadow == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg_set_buf(&sg_in[SG_AEAD_TEXT], data_in_shadow, data_in_size);
|
||||
|
||||
memcpy(data_in_shadow, data_in, data_in_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_in[SG_AEAD_TEXT], data_in, data_in_size);
|
||||
}
|
||||
|
||||
if (!virt_addr_valid(data_out)) {
|
||||
data_out_shadow = kmalloc(data_in_size, GFP_KERNEL);
|
||||
if (data_out_shadow == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg_set_buf(&sg_out[SG_AEAD_TEXT], data_out_shadow, data_in_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_out[SG_AEAD_TEXT], data_out, data_in_size);
|
||||
}
|
||||
|
||||
if (!virt_addr_valid(tag)) {
|
||||
tag_shadow = kmalloc(tag_size, GFP_KERNEL);
|
||||
if (tag_shadow == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg_set_buf(&sg_in[SG_AEAD_SIG], tag_shadow, tag_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_SIG], tag_shadow, tag_size);
|
||||
|
||||
if(!enc)
|
||||
memcpy(tag_shadow, tag, tag_size);
|
||||
} else {
|
||||
sg_set_buf(&sg_in[SG_AEAD_SIG], tag, tag_size);
|
||||
sg_set_buf(&sg_out[SG_AEAD_SIG], tag, tag_size);
|
||||
}
|
||||
|
||||
rc = lkca_aead_internal(aead, req, key, key_size, iv, iv_size,
|
||||
sg_in, sg_out, a_data_size, data_in_size,
|
||||
data_out_size, tag_size, enc);
|
||||
|
||||
if (enc && (tag_shadow != NULL))
|
||||
memcpy((uint8_t *) tag, tag_shadow, tag_size);
|
||||
|
||||
if (data_out_shadow != NULL)
|
||||
memcpy(data_out, data_out_shadow, data_in_size);
|
||||
|
||||
out:
|
||||
if (a_data_shadow != NULL)
|
||||
kfree(a_data_shadow);
|
||||
if (data_in_shadow != NULL)
|
||||
kfree(data_in_shadow);
|
||||
if (data_out != NULL)
|
||||
kfree(data_out_shadow);
|
||||
if (tag != NULL)
|
||||
kfree(tag_shadow);
|
||||
if (aead != NULL)
|
||||
crypto_free_aead(aead);
|
||||
if (req != NULL)
|
||||
aead_request_free(req);
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Wrapper to make look like libspdm
|
||||
bool libspdm_aead_gcm_prealloc(void **context)
|
||||
{
|
||||
return libspdm_aead_prealloc(context, "gcm(aes)") == 0;
|
||||
}
|
||||
|
||||
bool libspdm_aead_aes_gcm_encrypt_prealloc(void *context,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag_out, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (data_in_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (a_data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (iv_size != 12) {
|
||||
return false;
|
||||
}
|
||||
switch (key_size) {
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if ((tag_size < 12) || (tag_size > 16)) {
|
||||
return false;
|
||||
}
|
||||
if (data_out_size != NULL) {
|
||||
if ((*data_out_size > INT_MAX) ||
|
||||
(*data_out_size < data_in_size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = libspdm_aead_prealloced(context, key, key_size, iv, iv_size,
|
||||
a_data, a_data_size, data_in, data_in_size,
|
||||
tag_out, tag_size, data_out, data_out_size, true);
|
||||
|
||||
*data_out_size = data_in_size;
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
bool libspdm_aead_aes_gcm_decrypt_prealloc(void *context,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size)
|
||||
{
|
||||
int ret;
|
||||
if (data_in_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (a_data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (iv_size != 12) {
|
||||
return false;
|
||||
}
|
||||
switch (key_size) {
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if ((tag_size < 12) || (tag_size > 16)) {
|
||||
return false;
|
||||
}
|
||||
if (data_out_size != NULL) {
|
||||
if ((*data_out_size > INT_MAX) ||
|
||||
(*data_out_size < data_in_size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = libspdm_aead_prealloced(context, key, key_size, iv, iv_size,
|
||||
a_data, a_data_size, data_in, data_in_size,
|
||||
(uint8_t *) tag, tag_size, data_out, data_out_size, false);
|
||||
|
||||
*data_out_size = data_in_size;
|
||||
|
||||
return ret == 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Prototypes and checks taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
bool libspdm_aead_aes_gcm_encrypt(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag_out, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (data_in_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (a_data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (iv_size != 12) {
|
||||
return false;
|
||||
}
|
||||
switch (key_size) {
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if ((tag_size < 12) || (tag_size > 16)) {
|
||||
return false;
|
||||
}
|
||||
if (data_out_size != NULL) {
|
||||
if ((*data_out_size > INT_MAX) ||
|
||||
(*data_out_size < data_in_size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = libspdm_aead(key, key_size, iv, iv_size, a_data, a_data_size,
|
||||
data_in, data_in_size, tag_out, tag_size,
|
||||
data_out, data_out_size, true, "gcm(aes)");
|
||||
|
||||
*data_out_size = data_in_size;
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
bool libspdm_aead_aes_gcm_decrypt(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size)
|
||||
{
|
||||
int ret;
|
||||
if (data_in_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (a_data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (iv_size != 12) {
|
||||
return false;
|
||||
}
|
||||
switch (key_size) {
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if ((tag_size < 12) || (tag_size > 16)) {
|
||||
return false;
|
||||
}
|
||||
if (data_out_size != NULL) {
|
||||
if ((*data_out_size > INT_MAX) ||
|
||||
(*data_out_size < data_in_size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = libspdm_aead(key, key_size, iv, iv_size, a_data, a_data_size,
|
||||
data_in, data_in_size, tag, tag_size,
|
||||
data_out, data_out_size, false, "gcm(aes)");
|
||||
|
||||
*data_out_size = data_in_size;
|
||||
|
||||
return ret == 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Comments, prototypes and checks taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
static bool lkca_ecdsa_sign(void *ec_context,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
uint8_t *signature, size_t *sig_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
|
||||
size_t public_key_size)
|
||||
{
|
||||
if (ec_context == NULL || public_key == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_ec_set_pub_key(ec_context, public_key, public_key_size);
|
||||
}
|
||||
|
||||
bool libspdm_ec_get_pub_key(void *ec_context, uint8_t *public_key,
|
||||
size_t *public_key_size)
|
||||
{
|
||||
if (ec_context == NULL || public_key_size == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (public_key == NULL && *public_key_size != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_ec_get_pub_key(ec_context, public_key, public_key_size);
|
||||
}
|
||||
|
||||
bool libspdm_ec_check_key(const void *ec_context)
|
||||
{
|
||||
/* TBD*/
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_ec_generate_key(void *ec_context, uint8_t *public_data,
|
||||
size_t *public_size)
|
||||
{
|
||||
if (ec_context == NULL || public_size == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (public_data == NULL && *public_size != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_ec_generate_key(ec_context, public_data, public_size);
|
||||
}
|
||||
|
||||
bool libspdm_ec_compute_key(void *ec_context, const uint8_t *peer_public,
|
||||
size_t peer_public_size, uint8_t *key,
|
||||
size_t *key_size)
|
||||
{
|
||||
if (ec_context == NULL || peer_public == NULL || key_size == NULL ||
|
||||
key == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (peer_public_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_ec_compute_key(ec_context, peer_public, peer_public_size, key,
|
||||
key_size);
|
||||
}
|
||||
|
||||
bool libspdm_ecdsa_sign(void *ec_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
uint8_t *signature, size_t *sig_size)
|
||||
{
|
||||
if (ec_context == NULL || message_hash == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (signature == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (hash_nid) {
|
||||
case LIBSPDM_CRYPTO_NID_SHA256:
|
||||
if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIBSPDM_CRYPTO_NID_SHA384:
|
||||
if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIBSPDM_CRYPTO_NID_SHA512:
|
||||
if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_ecdsa_sign(ec_context, message_hash, hash_size, signature, sig_size);
|
||||
}
|
||||
|
||||
bool libspdm_ecdsa_verify(void *ec_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
const uint8_t *signature, size_t sig_size)
|
||||
{
|
||||
if (ec_context == NULL || message_hash == NULL || signature == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sig_size > INT_MAX || sig_size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (hash_nid) {
|
||||
case LIBSPDM_CRYPTO_NID_SHA256:
|
||||
if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIBSPDM_CRYPTO_NID_SHA384:
|
||||
if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIBSPDM_CRYPTO_NID_SHA512:
|
||||
if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_ecdsa_verify(ec_context, hash_nid, message_hash, hash_size,
|
||||
signature, sig_size);
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
#ifdef USE_LKCA
|
||||
#include <linux/module.h>
|
||||
MODULE_SOFTDEP("pre: ecdh_generic,ecdsa_generic");
|
||||
|
||||
#include <crypto/akcipher.h>
|
||||
#include <crypto/ecdh.h>
|
||||
#include <crypto/internal/ecc.h>
|
||||
|
||||
struct ecc_ctx {
|
||||
unsigned int curve_id;
|
||||
u64 priv_key[ECC_MAX_DIGITS]; // In big endian
|
||||
|
||||
struct {
|
||||
// ecdsa wants byte preceding pub_key to be set to '4'
|
||||
u64 pub_key_prefix;
|
||||
u64 pub_key[2 * ECC_MAX_DIGITS];
|
||||
};
|
||||
|
||||
bool pub_key_set;
|
||||
bool priv_key_set;
|
||||
char const *name;
|
||||
int size;
|
||||
};
|
||||
#endif
|
||||
|
||||
void *libspdm_ec_new_by_nid(size_t nid)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return NULL;
|
||||
#else
|
||||
struct ecc_ctx *ctx;
|
||||
|
||||
if ((nid != LIBSPDM_CRYPTO_NID_SECP256R1) && (nid != LIBSPDM_CRYPTO_NID_SECP384R1)){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nid == LIBSPDM_CRYPTO_NID_SECP256R1) {
|
||||
ctx->curve_id = ECC_CURVE_NIST_P256;
|
||||
ctx->size = 64;
|
||||
ctx->name = "ecdsa-nist-p256";
|
||||
} else {
|
||||
ctx->curve_id = ECC_CURVE_NIST_P384;
|
||||
ctx->size = 96;
|
||||
ctx->name = "ecdsa-nist-p384";
|
||||
}
|
||||
ctx->pub_key_set = false;
|
||||
ctx->priv_key_set = false;
|
||||
|
||||
return ctx;
|
||||
#endif
|
||||
}
|
||||
|
||||
void libspdm_ec_free(void *ec_context)
|
||||
{
|
||||
#ifdef USE_LKCA
|
||||
kfree(ec_context);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_ecdsa_set_priv_key(void *context, uint8_t *key, size_t key_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
struct ecc_ctx *ctx = context;
|
||||
unsigned int ndigits = ctx->size / 16;
|
||||
|
||||
if (key_size != (ctx->size / 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(ctx->priv_key, key, key_size);
|
||||
|
||||
// XXX: if this fails, do we want to retry generating new key?
|
||||
if(ecc_make_pub_key(ctx->curve_id, ndigits, ctx->priv_key, ctx->pub_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->pub_key_set = true;
|
||||
ctx->priv_key_set = true;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
|
||||
size_t public_key_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
struct ecc_ctx *ctx = ec_context;
|
||||
struct ecc_point pub_key;
|
||||
unsigned int ndigits;
|
||||
|
||||
if (public_key_size != ctx->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can reuse pub_key for now
|
||||
ndigits = ctx->size / 16;
|
||||
pub_key = ECC_POINT_INIT(ctx->pub_key, ctx->pub_key + ndigits, ndigits);
|
||||
|
||||
ecc_swap_digits(public_key, ctx->pub_key, ndigits);
|
||||
ecc_swap_digits(((u64 *)public_key) + ndigits, ctx->pub_key + ndigits, ndigits);
|
||||
if(ecc_is_pubkey_valid_full(ecc_get_curve(ctx->curve_id), &pub_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(ctx->pub_key, public_key, public_key_size);
|
||||
ctx->pub_key_set = true;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_ec_get_pub_key(void *ec_context, uint8_t *public_key,
|
||||
size_t *public_key_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
struct ecc_ctx *ctx = ec_context;
|
||||
|
||||
if (*public_key_size < ctx->size) {
|
||||
*public_key_size = ctx->size;
|
||||
return false;
|
||||
}
|
||||
*public_key_size = ctx->size;
|
||||
|
||||
memcpy(public_key, ctx->pub_key, ctx->size);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_ec_generate_key(void *ec_context, uint8_t *public_data,
|
||||
size_t *public_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
struct ecc_ctx *ctx = ec_context;
|
||||
|
||||
unsigned int ndigits = ctx->size / 16;
|
||||
|
||||
if(ecc_gen_privkey(ctx->curve_id, ndigits, ctx->priv_key)) {
|
||||
return false;
|
||||
}
|
||||
// XXX: if this fails, do we want to retry generating new key?
|
||||
if(ecc_make_pub_key(ctx->curve_id, ndigits, ctx->priv_key, ctx->pub_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(public_data, ctx->pub_key, ctx->size);
|
||||
*public_size = ctx->size;
|
||||
ctx->priv_key_set = true;
|
||||
ctx->pub_key_set = true;
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_ec_compute_key(void *ec_context, const uint8_t *peer_public,
|
||||
size_t peer_public_size, uint8_t *key,
|
||||
size_t *key_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
struct ecc_ctx *ctx = ec_context;
|
||||
|
||||
if (peer_public_size != ctx->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ctx->priv_key_set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ctx->size / 2) > *key_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crypto_ecdh_shared_secret(ctx->curve_id, ctx->size / 16,
|
||||
(const u64 *) ctx->priv_key,
|
||||
(const u64 *) peer_public,
|
||||
(u64 *) key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*key_size = ctx->size / 2;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid,
|
||||
const uint8_t *message_hash, size_t hash_size,
|
||||
const uint8_t *signature, size_t sig_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
struct ecc_ctx *ctx = ec_context;
|
||||
|
||||
// Roundabout way
|
||||
u64 ber_max_len = 3 + 2 * (4 + (ECC_MAX_BYTES));
|
||||
u64 ber_len = 0;
|
||||
u8 *ber = NULL;
|
||||
u8 *pub_key;
|
||||
struct akcipher_request *req = NULL;
|
||||
struct crypto_akcipher *tfm = NULL;
|
||||
struct scatterlist sg;
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
int err;
|
||||
|
||||
if (sig_size != ctx->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ctx->pub_key_set == false){
|
||||
return false;
|
||||
}
|
||||
|
||||
tfm = crypto_alloc_akcipher(ctx->name, CRYPTO_ALG_TYPE_AKCIPHER, 0);
|
||||
if (IS_ERR(tfm)) {
|
||||
pr_info("ALLOC FAILED\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
pub_key = (u8 *) ctx->pub_key;
|
||||
pub_key--; // Go back into byte of pub_key_prefix
|
||||
*pub_key = 4; // And set it to 4 to placate kernel
|
||||
if ((err = crypto_akcipher_set_pub_key(tfm, pub_key, ctx->size + 1)) != 0) {
|
||||
pr_info("SET PUB KEY FAILED: %d\n", -err);
|
||||
goto failTfm;
|
||||
}
|
||||
|
||||
req = akcipher_request_alloc(tfm, GFP_KERNEL);
|
||||
if (IS_ERR(req)) {
|
||||
pr_info("REQUEST ALLOC FAILED\n");
|
||||
goto failTfm;
|
||||
}
|
||||
|
||||
// We concatenate signature and hash and ship it to kernel
|
||||
ber = kmalloc(ber_max_len + hash_size, GFP_KERNEL);
|
||||
if (ber == NULL) {
|
||||
goto failReq;
|
||||
}
|
||||
|
||||
// XXX: NOTE THIS WILL WORK ONLY FOR 256 AND 384 bits. For larger keys
|
||||
// length field will be longer than 1 byte and I haven't taken care of that!
|
||||
|
||||
// Signature
|
||||
ber[ber_len++] = 0x30;
|
||||
ber[ber_len++] = 2 * (2 + ctx->size / 2);
|
||||
ber[ber_len++] = 0x02;
|
||||
if (signature[0] > 127) {
|
||||
ber[ber_len++] = ctx->size / 2 + 1;
|
||||
ber[1]++;
|
||||
ber[ber_len++] = 0;
|
||||
} else {
|
||||
ber[ber_len++] = ctx->size / 2;
|
||||
}
|
||||
memcpy(ber + ber_len, signature, sig_size / 2);
|
||||
ber_len += sig_size / 2;
|
||||
ber[ber_len++] = 0x02;
|
||||
if (signature[sig_size / 2] > 127) {
|
||||
ber[ber_len++] = ctx->size / 2 + 1;
|
||||
ber[1]++;
|
||||
ber[ber_len++] = 0;
|
||||
} else {
|
||||
ber[ber_len++] = ctx->size / 2;
|
||||
}
|
||||
memcpy(ber + ber_len, signature + sig_size / 2, sig_size / 2);
|
||||
ber_len += sig_size / 2;
|
||||
|
||||
// Just append hash, for scatterlists it can't be on stack anyway
|
||||
memcpy(ber + ber_len, message_hash, hash_size);
|
||||
|
||||
sg_init_one(&sg, ber, ber_len + hash_size);
|
||||
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait);
|
||||
akcipher_request_set_crypt(req, &sg, NULL, ber_len, hash_size);
|
||||
err = crypto_wait_req(crypto_akcipher_verify(req), &wait);
|
||||
|
||||
if (err != 0){
|
||||
pr_info("Verify FAILED %d\n", -err);
|
||||
}
|
||||
|
||||
kfree(ber);
|
||||
failReq:
|
||||
akcipher_request_free(req);
|
||||
failTfm:
|
||||
crypto_free_akcipher(tfm);
|
||||
|
||||
return err == 0;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
// RFC 5869 has some very non-intuitive points, reading it is advised
|
||||
static bool lkca_hkdf_expand_only(struct crypto_shash *alg,
|
||||
const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
int ret;
|
||||
int i;
|
||||
uint8_t ctr = 1;
|
||||
uint8_t tmp[HASH_MAX_DIGESTSIZE];
|
||||
SHASH_DESC_ON_STACK(desc, alg);
|
||||
desc->tfm = alg;
|
||||
|
||||
ret = crypto_shash_setkey(desc->tfm, prk, prk_size);
|
||||
if (ret != 0) {
|
||||
pr_info("key size mismatch %ld\n", prk_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0, ctr = 1; i < out_size; i += prk_size, ctr++) {
|
||||
ret = crypto_shash_init(desc);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
ret = crypto_shash_update(desc, out + i - prk_size, prk_size);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (info_size > 0) {
|
||||
ret = crypto_shash_update(desc, info, info_size);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(desc, &ctr, 1);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if ((out_size - i) < prk_size) {
|
||||
ret = crypto_shash_final(desc, tmp);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
memcpy(out + i, tmp, out_size - i);
|
||||
memzero_explicit(tmp, sizeof(tmp));
|
||||
} else {
|
||||
ret = crypto_shash_final(desc, out + i);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hkdf_extract_and_expand(const char *alg_name,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
int ret = 0;
|
||||
struct crypto_shash *alg;
|
||||
uint8_t prk[HASH_MAX_DIGESTSIZE];
|
||||
|
||||
if (key == NULL || salt == NULL || info == NULL || out == NULL ||
|
||||
key_size > sizeof(prk) || salt_size > INT_MAX || info_size > INT_MAX ||
|
||||
out_size > (sizeof(prk) * 255)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
alg = crypto_alloc_shash(alg_name, 0, 0);
|
||||
if (IS_ERR(alg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_setkey(alg, salt, salt_size);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
ret = crypto_shash_tfm_digest(alg, key, key_size, prk);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = !lkca_hkdf_expand_only(alg, prk, crypto_shash_digestsize(alg), info, info_size, out, out_size);
|
||||
|
||||
out:
|
||||
crypto_free_shash(alg);
|
||||
return ret == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hkdf_expand(const char *alg_name,
|
||||
const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
bool ret = false;
|
||||
struct crypto_shash *alg;
|
||||
|
||||
if (prk == NULL || info == NULL || out == NULL || prk_size > (512 / 8) ||
|
||||
info_size > INT_MAX || (out_size > (prk_size * 255))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
alg = crypto_alloc_shash(alg_name, 0, 0);
|
||||
if (IS_ERR(alg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = lkca_hkdf_expand_only(alg, prk, prk_size, info, info_size, out, out_size);
|
||||
|
||||
crypto_free_shash(alg);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Prototypes and checks taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
bool libspdm_hkdf_sha256_extract_and_expand(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
return lkca_hkdf_extract_and_expand("hmac(sha256)", key, key_size,
|
||||
salt, salt_size, info, info_size,
|
||||
out, out_size);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha256_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size)
|
||||
{
|
||||
if (prk_out_size != (256 / 8))
|
||||
return false;
|
||||
|
||||
return libspdm_hmac_sha256_all(key, key_size, salt, salt_size, prk_out);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha256_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
return lkca_hkdf_expand("hmac(sha256)", prk, prk_size, info, info_size,
|
||||
out, out_size);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha384_extract_and_expand(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
return lkca_hkdf_extract_and_expand("hmac(sha384)", key, key_size,
|
||||
salt, salt_size, info, info_size,
|
||||
out, out_size);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha384_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size)
|
||||
{
|
||||
if (prk_out_size != (384 / 8))
|
||||
return false;
|
||||
|
||||
return libspdm_hmac_sha384_all(key, key_size, salt, salt_size, prk_out);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha384_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
return lkca_hkdf_expand("hmac(sha384)", prk, prk_size, info, info_size,
|
||||
out, out_size);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha512_extract_and_expand(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
return lkca_hkdf_extract_and_expand("hmac(sha512)", key, key_size,
|
||||
salt, salt_size, info, info_size, out,
|
||||
out_size);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha512_extract(const uint8_t *key, size_t key_size,
|
||||
const uint8_t *salt, size_t salt_size,
|
||||
uint8_t *prk_out, size_t prk_out_size)
|
||||
{
|
||||
if (prk_out_size != (512 / 8))
|
||||
return false;
|
||||
|
||||
return libspdm_hmac_sha512_all(key, key_size, salt, salt_size, prk_out);
|
||||
}
|
||||
|
||||
bool libspdm_hkdf_sha512_expand(const uint8_t *prk, size_t prk_size,
|
||||
const uint8_t *info, size_t info_size,
|
||||
uint8_t *out, size_t out_size)
|
||||
{
|
||||
return lkca_hkdf_expand("hmac(sha512)", prk, prk_size, info, info_size,
|
||||
out, out_size);
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Prototypes and checks taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
void *libspdm_hmac_sha256_new(void)
|
||||
{
|
||||
return lkca_hash_new("hmac(sha256)");
|
||||
}
|
||||
|
||||
void libspdm_hmac_sha256_free(void *hmac_sha256_ctx)
|
||||
{
|
||||
lkca_hash_free(hmac_sha256_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha256_set_key(void *hmac_sha256_ctx, const uint8_t *key,
|
||||
size_t key_size)
|
||||
{
|
||||
if (hmac_sha256_ctx == NULL)
|
||||
return false;
|
||||
|
||||
return lkca_hmac_set_key(hmac_sha256_ctx, key, key_size);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha256_duplicate(const void *hmac_sha256_ctx,
|
||||
void *new_hmac_sha256_ctx)
|
||||
{
|
||||
if (hmac_sha256_ctx == NULL || new_hmac_sha256_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hmac_duplicate(new_hmac_sha256_ctx, hmac_sha256_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha256_update(void *hmac_sha256_ctx, const void *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (hmac_sha256_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(hmac_sha256_ctx, data, data_size);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha256_final(void *hmac_sha256_ctx, uint8_t *hmac_value)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (hmac_sha256_ctx == NULL || hmac_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_final(hmac_sha256_ctx, hmac_value);
|
||||
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha256_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value)
|
||||
{
|
||||
if (hmac_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hmac_all("hmac(sha256)", key, key_size, data, data_size, hmac_value);
|
||||
}
|
||||
|
||||
void *libspdm_hmac_sha384_new(void)
|
||||
{
|
||||
return lkca_hash_new("hmac(sha384)");
|
||||
}
|
||||
|
||||
void libspdm_hmac_sha384_free(void *hmac_sha384_ctx)
|
||||
{
|
||||
lkca_hash_free(hmac_sha384_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha384_set_key(void *hmac_sha384_ctx, const uint8_t *key,
|
||||
size_t key_size)
|
||||
{
|
||||
if (hmac_sha384_ctx == NULL)
|
||||
return false;
|
||||
|
||||
return lkca_hmac_set_key(hmac_sha384_ctx, key, key_size);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha384_duplicate(const void *hmac_sha384_ctx,
|
||||
void *new_hmac_sha384_ctx)
|
||||
{
|
||||
if (hmac_sha384_ctx == NULL || new_hmac_sha384_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hmac_duplicate(new_hmac_sha384_ctx, hmac_sha384_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha384_update(void *hmac_sha384_ctx, const void *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (hmac_sha384_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(hmac_sha384_ctx, data, data_size);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha384_final(void *hmac_sha384_ctx, uint8_t *hmac_value)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (hmac_sha384_ctx == NULL || hmac_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_final(hmac_sha384_ctx, hmac_value);
|
||||
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha384_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value)
|
||||
{
|
||||
if (hmac_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hmac_all("hmac(sha384)", key, key_size, data, data_size, hmac_value);
|
||||
}
|
||||
|
||||
void *libspdm_hmac_sha512_new(void)
|
||||
{
|
||||
return lkca_hash_new("hmac(sha512)");
|
||||
}
|
||||
|
||||
void libspdm_hmac_sha512_free(void *hmac_sha512_ctx)
|
||||
{
|
||||
lkca_hash_free(hmac_sha512_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha512_set_key(void *hmac_sha512_ctx, const uint8_t *key,
|
||||
size_t key_size)
|
||||
{
|
||||
if (hmac_sha512_ctx == NULL)
|
||||
return false;
|
||||
|
||||
return lkca_hmac_set_key(hmac_sha512_ctx, key, key_size);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha512_duplicate(const void *hmac_sha512_ctx,
|
||||
void *new_hmac_sha512_ctx)
|
||||
{
|
||||
if (new_hmac_sha512_ctx == NULL || new_hmac_sha512_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hmac_duplicate(new_hmac_sha512_ctx, hmac_sha512_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha512_update(void *hmac_sha512_ctx, const void *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (hmac_sha512_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(hmac_sha512_ctx, data, data_size);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha512_final(void *hmac_sha512_ctx, uint8_t *hmac_value)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (hmac_sha512_ctx == NULL || hmac_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_final(hmac_sha512_ctx, hmac_value);
|
||||
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_hmac_sha512_all(const void *data, size_t data_size,
|
||||
const uint8_t *key, size_t key_size,
|
||||
uint8_t *hmac_value)
|
||||
{
|
||||
if (hmac_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hmac_all("hmac(sha512)", key, key_size, data, data_size, hmac_value);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
// This is non-gpl symbol and not part of LKCA so no need to stub it out
|
||||
bool libspdm_random_bytes(uint8_t *output, size_t size)
|
||||
{
|
||||
get_random_bytes(output, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is specifically allowed by spdm
|
||||
bool libspdm_random_seed(const uint8_t *seed, size_t seed_size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Comments, prototypes and checks taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
void *libspdm_sha256_new(void)
|
||||
{
|
||||
return lkca_hash_new("sha256");
|
||||
}
|
||||
|
||||
void libspdm_sha256_free(void *sha256_ctx)
|
||||
{
|
||||
lkca_hash_free(sha256_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_sha256_init(void *sha256_context)
|
||||
{
|
||||
return crypto_shash_init(sha256_context) == 0;
|
||||
}
|
||||
|
||||
bool libspdm_sha256_duplicate(const void *sha256_context,
|
||||
void *new_sha256_context)
|
||||
{
|
||||
if (sha256_context == NULL || new_sha256_context == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hash_duplicate(new_sha256_context, sha256_context);
|
||||
}
|
||||
|
||||
bool libspdm_sha256_update(void *sha256_context, const void *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (sha256_context == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(sha256_context, data, data_size);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_sha256_final(void *sha256_context, uint8_t *hash_value)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (sha256_context == NULL || hash_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_final(sha256_context, hash_value);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_sha256_hash_all(const void *data, size_t data_size,
|
||||
uint8_t *hash_value)
|
||||
{
|
||||
if (hash_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hash_all("sha256", data, data_size, hash_value);
|
||||
}
|
||||
|
||||
void *libspdm_sha384_new(void)
|
||||
{
|
||||
return lkca_hash_new("sha384");
|
||||
}
|
||||
|
||||
void libspdm_sha384_free(void *sha384_ctx)
|
||||
{
|
||||
lkca_hash_free(sha384_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_sha384_init(void *sha384_context)
|
||||
{
|
||||
return crypto_shash_init(sha384_context) == 0;
|
||||
}
|
||||
|
||||
bool libspdm_sha384_duplicate(const void *sha384_context,
|
||||
void *new_sha384_context)
|
||||
{
|
||||
if (sha384_context == NULL || new_sha384_context == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hash_duplicate(new_sha384_context, sha384_context);
|
||||
}
|
||||
|
||||
bool libspdm_sha384_update(void *sha384_context, const void *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (sha384_context == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(sha384_context, data, data_size);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_sha384_final(void *sha384_context, uint8_t *hash_value)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (sha384_context == NULL || hash_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_final(sha384_context, hash_value);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_sha384_hash_all(const void *data, size_t data_size,
|
||||
uint8_t *hash_value)
|
||||
{
|
||||
if (hash_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hash_all("sha384", data, data_size, hash_value);
|
||||
}
|
||||
|
||||
void *libspdm_sha512_new(void)
|
||||
{
|
||||
return lkca_hash_new("sha512");
|
||||
}
|
||||
|
||||
void libspdm_sha512_free(void *sha512_ctx)
|
||||
{
|
||||
lkca_hash_free(sha512_ctx);
|
||||
}
|
||||
|
||||
bool libspdm_sha512_init(void *sha512_context)
|
||||
{
|
||||
return crypto_shash_init(sha512_context) == 0;
|
||||
}
|
||||
|
||||
bool libspdm_sha512_duplicate(const void *sha512_context,
|
||||
void *new_sha512_context)
|
||||
{
|
||||
if (sha512_context == NULL || new_sha512_context == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hash_duplicate(new_sha512_context, sha512_context);
|
||||
}
|
||||
|
||||
bool libspdm_sha512_update(void *sha512_context, const void *data,
|
||||
size_t data_size)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (sha512_context == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_update(sha512_context, data, data_size);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_sha512_final(void *sha512_context, uint8_t *hash_value)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (sha512_context == NULL || hash_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_final(sha512_context, hash_value);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_sha512_hash_all(const void *data, size_t data_size,
|
||||
uint8_t *hash_value)
|
||||
{
|
||||
if (hash_value == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (data == NULL && data_size != 0) {
|
||||
return false;
|
||||
}
|
||||
if (data_size > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lkca_hash_all("sha512", data, data_size, hash_value);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
#ifdef USE_LKCA
|
||||
#ifndef NV_CRYPTO_TFM_CTX_ALIGNED_PRESENT
|
||||
#include <crypto/internal/hash.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void *lkca_hash_new(const char* alg_name)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return NULL;
|
||||
#else
|
||||
//XXX: can we reuse crypto_shash part and just allocate desc
|
||||
struct crypto_shash *alg;
|
||||
struct shash_desc *desc;
|
||||
|
||||
alg = crypto_alloc_shash(alg_name, 0, 0);
|
||||
if (IS_ERR(alg)) {
|
||||
printk (KERN_INFO "Failed to alloc %s\n", alg_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(alg), GFP_KERNEL);
|
||||
if (desc == NULL){
|
||||
printk (KERN_INFO "Kernel out of mem\n");
|
||||
crypto_free_shash(alg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc->tfm = alg;
|
||||
|
||||
return desc;
|
||||
#endif
|
||||
}
|
||||
|
||||
void lkca_hash_free(struct shash_desc *ctx)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
#else
|
||||
crypto_free_shash(ctx->tfm);
|
||||
kfree(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hash_duplicate(struct shash_desc *dst, struct shash_desc const *src)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
SHASH_DESC_ON_STACK(tmp, src);
|
||||
|
||||
if (crypto_shash_export((struct shash_desc *) src, tmp)) {
|
||||
return false;
|
||||
}
|
||||
if (crypto_shash_import(dst, tmp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hmac_duplicate(struct shash_desc *dst, struct shash_desc const *src)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
// in LKCA hmac export doesn't export ipad/opad, so we need to WAR it
|
||||
|
||||
struct crypto_shash *src_tfm = src->tfm;
|
||||
struct crypto_shash *dst_tfm = dst->tfm;
|
||||
int ss = crypto_shash_statesize(dst_tfm);
|
||||
|
||||
#ifdef NV_CRYPTO_TFM_CTX_ALIGNED_PRESENT
|
||||
char *src_ipad = crypto_tfm_ctx_aligned(&src_tfm->base);
|
||||
char *dst_ipad = crypto_tfm_ctx_aligned(&dst_tfm->base);
|
||||
#else
|
||||
int ctx_size = crypto_shash_alg(dst_tfm)->base.cra_ctxsize;
|
||||
char *src_ipad = crypto_shash_ctx(src_tfm);
|
||||
char *dst_ipad = crypto_shash_ctx(dst_tfm);
|
||||
/*
|
||||
* Actual struct definition is hidden, so I assume data we need is at
|
||||
* the end. In 6.0 the struct has a pointer to crpyto_shash followed by:
|
||||
* 'u8 ipad[statesize];', then 'u8 opad[statesize];'
|
||||
*/
|
||||
src_ipad += ctx_size - 2 * ss;
|
||||
dst_ipad += ctx_size - 2 * ss;
|
||||
#endif
|
||||
|
||||
memcpy(dst_ipad, src_ipad, crypto_shash_blocksize(src->tfm));
|
||||
memcpy(dst_ipad + ss, src_ipad + ss, crypto_shash_blocksize(src->tfm));
|
||||
crypto_shash_clear_flags(dst->tfm, CRYPTO_TFM_NEED_KEY);
|
||||
|
||||
return lkca_hash_duplicate(dst, src);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hash_all(const char* alg_name, const void *data,
|
||||
size_t data_size, uint8_t *hash_value)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
int ret;
|
||||
struct crypto_shash *alg;
|
||||
alg = crypto_alloc_shash(alg_name, 0, 0);
|
||||
if (IS_ERR(alg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_tfm_digest(alg, data, data_size, hash_value);
|
||||
|
||||
crypto_free_shash(alg);
|
||||
|
||||
return (ret == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hmac_set_key(struct shash_desc *desc, const uint8_t *key, size_t key_size)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
int ret;
|
||||
ret = crypto_shash_setkey(desc->tfm, key, key_size);
|
||||
if (ret == 0) {
|
||||
ret = crypto_shash_init(desc);
|
||||
}
|
||||
return ret == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lkca_hmac_all(const char* alg_name, const uint8_t *key, size_t key_size,
|
||||
const uint8_t *data, size_t data_size, uint8_t *hash_value)
|
||||
{
|
||||
#ifndef USE_LKCA
|
||||
return false;
|
||||
#else
|
||||
int ret;
|
||||
struct crypto_shash *alg;
|
||||
alg = crypto_alloc_shash(alg_name, 0, 0);
|
||||
if (IS_ERR(alg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = crypto_shash_setkey(alg, key, key_size);
|
||||
|
||||
if (ret == 0){
|
||||
ret = crypto_shash_tfm_digest(alg, data, data_size, hash_value);
|
||||
}
|
||||
|
||||
crypto_free_shash(alg);
|
||||
|
||||
return (ret == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* libspdm_x509_verify_cert_chain, libspdm_x509_get_cert_from_cert_chain, check
|
||||
* and prototypes taken from DMTF: Copyright 2021-2022 DMTF. All rights reserved.
|
||||
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
|
||||
*/
|
||||
|
||||
#include "internal_crypt_lib.h"
|
||||
|
||||
#ifdef USE_LKCA
|
||||
#include <crypto/public_key.h>
|
||||
#include <keys/asymmetric-type.h>
|
||||
#endif
|
||||
|
||||
bool libspdm_x509_construct_certificate(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t **single_x509_cert)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_construct_certificate_stack(uint8_t **x509_stack, ...)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
void libspdm_x509_free(void *x509_cert)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
}
|
||||
|
||||
void libspdm_x509_stack_free(void *x509_stack)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
}
|
||||
|
||||
static bool lkca_asn1_get_tag(uint8_t const *ptr, uint8_t const *end,
|
||||
size_t *length, uint32_t tag)
|
||||
{
|
||||
uint64_t max_len = end - ptr;
|
||||
|
||||
// Chain must be less than 1 GB
|
||||
if ((max_len < 2) || (max_len > (1024 * 1024 * 1024))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only deal with universal and application tags
|
||||
if (ptr[0] != tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ptr[1] < 0x80) {
|
||||
*length = ptr[1] + 2;
|
||||
} else if (ptr[1] == 0x81) {
|
||||
if (max_len < 3) {
|
||||
return false;
|
||||
}
|
||||
*length = ptr[2] + 3;
|
||||
} else if (ptr[1] == 0x82) {
|
||||
if (max_len < 4) {
|
||||
return false;
|
||||
}
|
||||
*length = (ptr[2] << 8) + ptr[3] + 4;
|
||||
} else {
|
||||
// In theory it could be bigger than 64KB
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*length > max_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool libspdm_asn1_get_tag(uint8_t **ptr, const uint8_t *end, size_t *length,
|
||||
uint32_t tag)
|
||||
{
|
||||
return lkca_asn1_get_tag(*ptr, end, length, tag);
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_subject_name(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *cert_subject,
|
||||
size_t *subject_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_common_name(const uint8_t *cert, size_t cert_size,
|
||||
char *common_name,
|
||||
size_t *common_name_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
libspdm_x509_get_organization_name(const uint8_t *cert, size_t cert_size,
|
||||
char *name_buffer,
|
||||
size_t *name_buffer_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
|
||||
bool libspdm_rsa_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **rsa_context)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
#endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
|
||||
|
||||
bool libspdm_ec_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **ec_context)
|
||||
{
|
||||
#ifdef USE_LKCA
|
||||
bool ret = false;
|
||||
uint32_t key_size = 0;
|
||||
struct key_preparsed_payload lkca_cert;
|
||||
struct public_key *pub;
|
||||
|
||||
lkca_cert.data = cert;
|
||||
lkca_cert.datalen = cert_size;
|
||||
|
||||
if (cert == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(key_type_asymmetric.preparse(&lkca_cert)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub = lkca_cert.payload.data[asym_crypto];
|
||||
// -1 is since lkca prepends '4' to public keys...
|
||||
key_size = pub->keylen - 1;
|
||||
|
||||
if (key_size == (2 * 256 / 8)) {
|
||||
*ec_context = libspdm_ec_new_by_nid(LIBSPDM_CRYPTO_NID_SECP256R1);
|
||||
} else if (key_size == (2 * 384 / 8)) {
|
||||
*ec_context = libspdm_ec_new_by_nid(LIBSPDM_CRYPTO_NID_SECP384R1);
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (*ec_context == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Again skip '4' in key to be in line with spdm protocol. We will add it
|
||||
// back in ecda_verify
|
||||
if (!lkca_ec_set_pub_key(*ec_context, (char *) pub->key + 1, key_size)) {
|
||||
libspdm_ec_free(*ec_context);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
err:
|
||||
key_type_asymmetric.free_preparse(&lkca_cert);
|
||||
return ret;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool libspdm_ecd_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **ecd_context)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_sm2_get_public_key_from_x509(const uint8_t *cert, size_t cert_size,
|
||||
void **sm2_context)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int lkca_x509_verify_cert(const uint8_t *cert, size_t cert_size,
|
||||
const uint8_t *ca_cert, size_t ca_cert_size)
|
||||
{
|
||||
#ifdef USE_LKCA
|
||||
int ret;
|
||||
struct key_preparsed_payload lkca_cert;
|
||||
struct key_preparsed_payload lkca_ca_cert;
|
||||
|
||||
lkca_cert.data = cert;
|
||||
lkca_cert.datalen = cert_size;
|
||||
lkca_ca_cert.data = ca_cert;
|
||||
lkca_ca_cert.datalen = ca_cert_size;
|
||||
|
||||
ret = key_type_asymmetric.preparse(&lkca_cert);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = key_type_asymmetric.preparse(&lkca_ca_cert);
|
||||
if (ret) {
|
||||
key_type_asymmetric.free_preparse(&lkca_cert);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = public_key_verify_signature(lkca_ca_cert.payload.data[asym_crypto],
|
||||
lkca_cert.payload.data[asym_auth]);
|
||||
|
||||
key_type_asymmetric.free_preparse(&lkca_cert);
|
||||
key_type_asymmetric.free_preparse(&lkca_ca_cert);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool libspdm_x509_verify_cert(const uint8_t *cert, size_t cert_size,
|
||||
const uint8_t *ca_cert, size_t ca_cert_size)
|
||||
{
|
||||
return lkca_x509_verify_cert(cert, cert_size, ca_cert, ca_cert_size) == 0;
|
||||
}
|
||||
|
||||
bool libspdm_x509_verify_cert_chain(const uint8_t *root_cert, size_t root_cert_length,
|
||||
const uint8_t *cert_chain, size_t cert_chain_length)
|
||||
{
|
||||
size_t preceding_cert_len;
|
||||
const uint8_t *preceding_cert;
|
||||
size_t current_cert_len;
|
||||
const uint8_t *current_cert;
|
||||
bool verify_flag;
|
||||
int ret;
|
||||
|
||||
verify_flag = false;
|
||||
preceding_cert = root_cert;
|
||||
preceding_cert_len = root_cert_length;
|
||||
|
||||
current_cert = cert_chain;
|
||||
|
||||
|
||||
/* Get Current certificate from certificates buffer and Verify with preceding cert*/
|
||||
do {
|
||||
if (!lkca_asn1_get_tag(
|
||||
current_cert, cert_chain + cert_chain_length, ¤t_cert_len,
|
||||
LIBSPDM_CRYPTO_ASN1_CONSTRUCTED | LIBSPDM_CRYPTO_ASN1_SEQUENCE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lkca_x509_verify_cert(current_cert, current_cert_len,
|
||||
preceding_cert, preceding_cert_len);
|
||||
if (ret != 0) {
|
||||
verify_flag = false;
|
||||
break;
|
||||
} else {
|
||||
verify_flag = true;
|
||||
}
|
||||
|
||||
preceding_cert = current_cert;
|
||||
preceding_cert_len = current_cert_len;
|
||||
|
||||
current_cert = current_cert + current_cert_len;
|
||||
} while (true);
|
||||
|
||||
return verify_flag;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_cert_from_cert_chain(const uint8_t *cert_chain,
|
||||
size_t cert_chain_length,
|
||||
const int32_t cert_index, const uint8_t **cert,
|
||||
size_t *cert_length)
|
||||
{
|
||||
size_t asn1_len;
|
||||
int32_t current_index;
|
||||
size_t current_cert_len;
|
||||
const uint8_t *current_cert;
|
||||
|
||||
current_cert_len = 0;
|
||||
|
||||
/* Check input parameters.*/
|
||||
if ((cert_chain == NULL) || (cert == NULL) || (cert_index < -1) ||
|
||||
(cert_length == NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_cert = cert_chain;
|
||||
current_index = -1;
|
||||
|
||||
/* Traverse the certificate chain*/
|
||||
while (true) {
|
||||
/* Get asn1 tag len*/
|
||||
if (!lkca_asn1_get_tag(
|
||||
current_cert, cert_chain + cert_chain_length, &asn1_len,
|
||||
LIBSPDM_CRYPTO_ASN1_CONSTRUCTED | LIBSPDM_CRYPTO_ASN1_SEQUENCE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
current_cert_len = asn1_len;
|
||||
current_index++;
|
||||
|
||||
if (current_index == cert_index) {
|
||||
*cert = current_cert;
|
||||
*cert_length = current_cert_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
current_cert = current_cert + current_cert_len;
|
||||
}
|
||||
|
||||
/* If cert_index is -1, Return the last certificate*/
|
||||
if (cert_index == -1 && current_index >= 0) {
|
||||
*cert = current_cert - current_cert_len;
|
||||
*cert_length = current_cert_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_tbs_cert(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t **tbs_cert, size_t *tbs_cert_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_version(const uint8_t *cert, size_t cert_size,
|
||||
size_t *version)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_serial_number(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *serial_number,
|
||||
size_t *serial_number_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_issuer_name(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *cert_issuer,
|
||||
size_t *issuer_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
libspdm_x509_get_issuer_common_name(const uint8_t *cert, size_t cert_size,
|
||||
char *common_name,
|
||||
size_t *common_name_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size,
|
||||
char *name_buffer,
|
||||
size_t *name_buffer_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_signature_algorithm(const uint8_t *cert,
|
||||
size_t cert_size, uint8_t *oid,
|
||||
size_t *oid_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_extension_data(const uint8_t *cert, size_t cert_size,
|
||||
const uint8_t *oid, size_t oid_size,
|
||||
uint8_t *extension_data,
|
||||
size_t *extension_data_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_validity(const uint8_t *cert, size_t cert_size,
|
||||
uint8_t *from, size_t *from_size, uint8_t *to,
|
||||
size_t *to_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_key_usage(const uint8_t *cert, size_t cert_size,
|
||||
size_t *usage)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_extended_key_usage(const uint8_t *cert,
|
||||
size_t cert_size, uint8_t *usage,
|
||||
size_t *usage_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_get_extended_basic_constraints(const uint8_t *cert,
|
||||
size_t cert_size,
|
||||
uint8_t *basic_constraints,
|
||||
size_t *basic_constraints_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool libspdm_x509_set_date_time(char const *date_time_str, void *date_time, size_t *date_time_size)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t libspdm_x509_compare_date_time(const void *date_time1, const void *date_time2)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return -3;
|
||||
}
|
||||
|
||||
bool libspdm_gen_x509_csr(size_t hash_nid, size_t asym_nid,
|
||||
uint8_t *requester_info, size_t requester_info_length,
|
||||
void *context, char *subject_name,
|
||||
size_t *csr_len, uint8_t **csr_pointer)
|
||||
{
|
||||
LIBSPDM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2016-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LINUX_NVSWITCH_H
|
||||
#define LINUX_NVSWITCH_H
|
||||
|
||||
#include "nvmisc.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-kthread-q.h"
|
||||
#include "export_nvswitch.h"
|
||||
|
||||
#define NVSWITCH_SHORT_NAME "nvswi"
|
||||
|
||||
#define NVSWITCH_IRQ_NONE 0
|
||||
#define NVSWITCH_IRQ_MSIX 1
|
||||
#define NVSWITCH_IRQ_MSI 2
|
||||
#define NVSWITCH_IRQ_PIN 3
|
||||
|
||||
#define NVSWITCH_OS_ASSERT(_cond) \
|
||||
do { \
|
||||
if (!(_cond)) { \
|
||||
nvswitch_os_assert_log("NVSwitch: Assertion failed in %s() at %s:%d\n", \
|
||||
__FUNCTION__ , __FILE__, __LINE__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NVSWITCH_KMALLOC_LIMIT (128 * 1024)
|
||||
|
||||
#define nvswitch_os_malloc(_size) nvswitch_os_malloc_trace(_size, __FILE__, __LINE__)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head entry;
|
||||
struct i2c_adapter *adapter;
|
||||
} nvswitch_i2c_adapter_entry;
|
||||
|
||||
// Per-chip driver state
|
||||
typedef struct
|
||||
{
|
||||
char name[sizeof(NVSWITCH_DRIVER_NAME) + 4];
|
||||
char sname[sizeof(NVSWITCH_SHORT_NAME) + 4]; /* short name */
|
||||
int minor;
|
||||
NvUuid uuid;
|
||||
struct mutex device_mutex;
|
||||
nvswitch_device *lib_device; /* nvswitch library device */
|
||||
wait_queue_head_t wait_q_errors;
|
||||
void *bar0;
|
||||
struct nv_kthread_q task_q; /* Background task queue */
|
||||
struct nv_kthread_q_item task_item; /* Background dispatch task */
|
||||
atomic_t task_q_ready;
|
||||
wait_queue_head_t wait_q_shutdown;
|
||||
struct pci_dev *pci_dev;
|
||||
atomic_t ref_count;
|
||||
struct list_head list_node;
|
||||
NvBool unusable;
|
||||
NvU32 phys_id;
|
||||
NvU64 bios_ver;
|
||||
#if defined(CONFIG_PROC_FS)
|
||||
struct proc_dir_entry *procfs_dir;
|
||||
#endif
|
||||
NvU8 irq_mechanism;
|
||||
struct list_head i2c_adapter_list;
|
||||
} NVSWITCH_DEV;
|
||||
|
||||
|
||||
int nvswitch_map_status(NvlStatus status);
|
||||
int nvswitch_procfs_init(void);
|
||||
void nvswitch_procfs_exit(void);
|
||||
int nvswitch_procfs_device_add(NVSWITCH_DEV *nvswitch_dev);
|
||||
void nvswitch_procfs_device_remove(NVSWITCH_DEV *nvswitch_dev);
|
||||
struct i2c_adapter *nvswitch_i2c_add_adapter(NVSWITCH_DEV *nvswitch_dev, NvU32 port);
|
||||
void nvswitch_i2c_del_adapter(struct i2c_adapter *adapter);
|
||||
|
||||
#endif // LINUX_NVSWITCH_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nv-linux.h"
|
||||
#include "nv-caps.h"
|
||||
#include "nv-procfs.h"
|
||||
#include "nv-hash.h"
|
||||
|
||||
extern int NVreg_ModifyDeviceFiles;
|
||||
|
||||
/* sys_close() or __close_fd() */
|
||||
#include <linux/syscalls.h>
|
||||
|
||||
#define NV_CAP_DRV_MINOR_COUNT 8192
|
||||
|
||||
/* Hash table with 512 buckets */
|
||||
#define NV_CAP_HASH_BITS 9
|
||||
NV_DECLARE_HASHTABLE(g_nv_cap_hash_table, NV_CAP_HASH_BITS);
|
||||
|
||||
#define NV_CAP_HASH_SIZE NV_HASH_SIZE(g_nv_cap_hash_table)
|
||||
|
||||
#define nv_cap_hash_key(path) (nv_string_hash(path) % NV_CAP_HASH_SIZE)
|
||||
|
||||
typedef struct nv_cap_table_entry
|
||||
{
|
||||
/* name must be the first element */
|
||||
const char *name;
|
||||
int minor;
|
||||
struct hlist_node hlist;
|
||||
} nv_cap_table_entry_t;
|
||||
|
||||
#define NV_CAP_NUM_ENTRIES(_table) (sizeof(_table) / sizeof(_table[0]))
|
||||
|
||||
static nv_cap_table_entry_t g_nv_cap_nvlink_table[] =
|
||||
{
|
||||
{"/driver/nvidia-nvlink/capabilities/fabric-mgmt"}
|
||||
};
|
||||
|
||||
static nv_cap_table_entry_t g_nv_cap_mig_table[] =
|
||||
{
|
||||
{"/driver/nvidia/capabilities/mig/config"},
|
||||
{"/driver/nvidia/capabilities/mig/monitor"}
|
||||
};
|
||||
|
||||
static nv_cap_table_entry_t g_nv_cap_sys_table[] =
|
||||
{
|
||||
};
|
||||
|
||||
#define NV_CAP_MIG_CI_ENTRIES(_gi) \
|
||||
{_gi "/ci0/access"}, \
|
||||
{_gi "/ci1/access"}, \
|
||||
{_gi "/ci2/access"}, \
|
||||
{_gi "/ci3/access"}, \
|
||||
{_gi "/ci4/access"}, \
|
||||
{_gi "/ci5/access"}, \
|
||||
{_gi "/ci6/access"}, \
|
||||
{_gi "/ci7/access"}
|
||||
|
||||
#define NV_CAP_MIG_GI_ENTRIES(_gpu) \
|
||||
{_gpu "/gi0/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi0"), \
|
||||
{_gpu "/gi1/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi1"), \
|
||||
{_gpu "/gi2/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi2"), \
|
||||
{_gpu "/gi3/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi3"), \
|
||||
{_gpu "/gi4/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi4"), \
|
||||
{_gpu "/gi5/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi5"), \
|
||||
{_gpu "/gi6/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi6"), \
|
||||
{_gpu "/gi7/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi7"), \
|
||||
{_gpu "/gi8/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi8"), \
|
||||
{_gpu "/gi9/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi9"), \
|
||||
{_gpu "/gi10/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi10"), \
|
||||
{_gpu "/gi11/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi11"), \
|
||||
{_gpu "/gi12/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi12"), \
|
||||
{_gpu "/gi13/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi13"), \
|
||||
{_gpu "/gi14/access"}, \
|
||||
NV_CAP_MIG_CI_ENTRIES(_gpu "/gi14")
|
||||
|
||||
static nv_cap_table_entry_t g_nv_cap_mig_gpu_table[] =
|
||||
{
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu0/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu1/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu2/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu3/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu4/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu5/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu6/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu7/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu8/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu9/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu10/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu11/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu12/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu13/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu14/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu15/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu16/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu17/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu18/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu19/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu20/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu21/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu22/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu23/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu24/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu25/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu26/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu27/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu28/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu29/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu30/mig"),
|
||||
NV_CAP_MIG_GI_ENTRIES("/driver/nvidia/capabilities/gpu31/mig")
|
||||
};
|
||||
|
||||
struct nv_cap
|
||||
{
|
||||
char *path;
|
||||
char *name;
|
||||
int minor;
|
||||
int permissions;
|
||||
int modify;
|
||||
struct proc_dir_entry *parent;
|
||||
struct proc_dir_entry *entry;
|
||||
};
|
||||
|
||||
#define NV_CAP_PROCFS_WRITE_BUF_SIZE 128
|
||||
|
||||
typedef struct nv_cap_file_private
|
||||
{
|
||||
int minor;
|
||||
int permissions;
|
||||
int modify;
|
||||
char buffer[NV_CAP_PROCFS_WRITE_BUF_SIZE];
|
||||
off_t offset;
|
||||
} nv_cap_file_private_t;
|
||||
|
||||
struct
|
||||
{
|
||||
NvBool initialized;
|
||||
struct cdev cdev;
|
||||
dev_t devno;
|
||||
} g_nv_cap_drv;
|
||||
|
||||
#define NV_CAP_PROCFS_DIR "driver/nvidia-caps"
|
||||
#define NV_CAP_NAME_BUF_SIZE 128
|
||||
|
||||
static struct proc_dir_entry *nv_cap_procfs_dir;
|
||||
|
||||
static int nv_procfs_read_nvlink_minors(struct seq_file *s, void *v)
|
||||
{
|
||||
int i, count;
|
||||
char name[NV_CAP_NAME_BUF_SIZE];
|
||||
|
||||
count = NV_CAP_NUM_ENTRIES(g_nv_cap_nvlink_table);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (sscanf(g_nv_cap_nvlink_table[i].name,
|
||||
"/driver/nvidia-nvlink/capabilities/%s", name) == 1)
|
||||
{
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
seq_printf(s, "%s %d\n", name, g_nv_cap_nvlink_table[i].minor);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_procfs_read_sys_minors(struct seq_file *s, void *v)
|
||||
{
|
||||
int i, count;
|
||||
char name[NV_CAP_NAME_BUF_SIZE];
|
||||
|
||||
count = NV_CAP_NUM_ENTRIES(g_nv_cap_sys_table);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (sscanf(g_nv_cap_sys_table[i].name,
|
||||
"/driver/nvidia/capabilities/%s", name) == 1)
|
||||
{
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
seq_printf(s, "%s %d\n", name, g_nv_cap_sys_table[i].minor);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_procfs_read_mig_minors(struct seq_file *s, void *v)
|
||||
{
|
||||
int i, count, gpu;
|
||||
char name[NV_CAP_NAME_BUF_SIZE];
|
||||
|
||||
count = NV_CAP_NUM_ENTRIES(g_nv_cap_mig_table);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (sscanf(g_nv_cap_mig_table[i].name,
|
||||
"/driver/nvidia/capabilities/mig/%s", name) == 1)
|
||||
{
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
seq_printf(s, "%s %d\n", name, g_nv_cap_mig_table[i].minor);
|
||||
}
|
||||
}
|
||||
|
||||
count = NV_CAP_NUM_ENTRIES(g_nv_cap_mig_gpu_table);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (sscanf(g_nv_cap_mig_gpu_table[i].name,
|
||||
"/driver/nvidia/capabilities/gpu%d/mig/%s", &gpu, name) == 2)
|
||||
{
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
seq_printf(s, "gpu%d/%s %d\n",
|
||||
gpu, name, g_nv_cap_mig_gpu_table[i].minor);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NV_DEFINE_SINGLE_PROCFS_FILE_READ_ONLY(nvlink_minors, nv_system_pm_lock);
|
||||
|
||||
NV_DEFINE_SINGLE_PROCFS_FILE_READ_ONLY(mig_minors, nv_system_pm_lock);
|
||||
|
||||
NV_DEFINE_SINGLE_PROCFS_FILE_READ_ONLY(sys_minors, nv_system_pm_lock);
|
||||
|
||||
static void nv_cap_procfs_exit(void)
|
||||
{
|
||||
if (!nv_cap_procfs_dir)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PROC_FS)
|
||||
proc_remove(nv_cap_procfs_dir);
|
||||
#endif
|
||||
nv_cap_procfs_dir = NULL;
|
||||
}
|
||||
|
||||
int nv_cap_procfs_init(void)
|
||||
{
|
||||
static struct proc_dir_entry *file_entry;
|
||||
|
||||
nv_cap_procfs_dir = NV_CREATE_PROC_DIR(NV_CAP_PROCFS_DIR, NULL);
|
||||
if (nv_cap_procfs_dir == NULL)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
file_entry = NV_CREATE_PROC_FILE("mig-minors", nv_cap_procfs_dir,
|
||||
mig_minors, NULL);
|
||||
if (file_entry == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
file_entry = NV_CREATE_PROC_FILE("nvlink-minors", nv_cap_procfs_dir,
|
||||
nvlink_minors, NULL);
|
||||
if (file_entry == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
file_entry = NV_CREATE_PROC_FILE("sys-minors", nv_cap_procfs_dir,
|
||||
sys_minors, NULL);
|
||||
if (file_entry == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
nv_cap_procfs_exit();
|
||||
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
static int nv_cap_find_minor(char *path)
|
||||
{
|
||||
unsigned int key = nv_cap_hash_key(path);
|
||||
nv_cap_table_entry_t *entry;
|
||||
|
||||
nv_hash_for_each_possible(g_nv_cap_hash_table, entry, hlist, key)
|
||||
{
|
||||
if (strcmp(path, entry->name) == 0)
|
||||
{
|
||||
return entry->minor;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _nv_cap_table_init(nv_cap_table_entry_t *table, int count)
|
||||
{
|
||||
int i;
|
||||
unsigned int key;
|
||||
static int minor = 0;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
table[i].minor = minor++;
|
||||
INIT_HLIST_NODE(&table[i].hlist);
|
||||
key = nv_cap_hash_key(table[i].name);
|
||||
nv_hash_add(g_nv_cap_hash_table, &table[i].hlist, key);
|
||||
}
|
||||
|
||||
WARN_ON(minor > NV_CAP_DRV_MINOR_COUNT);
|
||||
}
|
||||
|
||||
#define nv_cap_table_init(table) \
|
||||
_nv_cap_table_init(table, NV_CAP_NUM_ENTRIES(table))
|
||||
|
||||
static void nv_cap_tables_init(void)
|
||||
{
|
||||
BUILD_BUG_ON(offsetof(nv_cap_table_entry_t, name) != 0);
|
||||
|
||||
nv_hash_init(g_nv_cap_hash_table);
|
||||
|
||||
nv_cap_table_init(g_nv_cap_nvlink_table);
|
||||
nv_cap_table_init(g_nv_cap_mig_table);
|
||||
nv_cap_table_init(g_nv_cap_mig_gpu_table);
|
||||
nv_cap_table_init(g_nv_cap_sys_table);
|
||||
}
|
||||
|
||||
static ssize_t nv_cap_procfs_write(struct file *file,
|
||||
const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
nv_cap_file_private_t *private = NULL;
|
||||
unsigned long bytes_left;
|
||||
char *proc_buffer;
|
||||
|
||||
private = ((struct seq_file *)file->private_data)->private;
|
||||
bytes_left = (sizeof(private->buffer) - private->offset - 1);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((bytes_left == 0) || (count > bytes_left))
|
||||
{
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
proc_buffer = &private->buffer[private->offset];
|
||||
|
||||
if (copy_from_user(proc_buffer, buffer, count))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "nv-caps: failed to copy in proc data!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
private->offset += count;
|
||||
proc_buffer[count] = '\0';
|
||||
|
||||
*pos = private->offset;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int nv_cap_procfs_read(struct seq_file *s, void *v)
|
||||
{
|
||||
nv_cap_file_private_t *private = s->private;
|
||||
|
||||
seq_printf(s, "%s: %d\n", "DeviceFileMinor", private->minor);
|
||||
seq_printf(s, "%s: %d\n", "DeviceFileMode", private->permissions);
|
||||
seq_printf(s, "%s: %d\n", "DeviceFileModify", private->modify);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_cap_procfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
nv_cap_file_private_t *private = NULL;
|
||||
int rc;
|
||||
nv_cap_t *cap = NV_PDE_DATA(inode);
|
||||
|
||||
NV_KMALLOC(private, sizeof(nv_cap_file_private_t));
|
||||
if (private == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
private->minor = cap->minor;
|
||||
private->permissions = cap->permissions;
|
||||
private->offset = 0;
|
||||
private->modify = cap->modify;
|
||||
|
||||
rc = single_open(file, nv_cap_procfs_read, private);
|
||||
if (rc < 0)
|
||||
{
|
||||
NV_KFREE(private, sizeof(nv_cap_file_private_t));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = nv_down_read_interruptible(&nv_system_pm_lock);
|
||||
if (rc < 0)
|
||||
{
|
||||
single_release(inode, file);
|
||||
NV_KFREE(private, sizeof(nv_cap_file_private_t));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int nv_cap_procfs_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
nv_cap_file_private_t *private = NULL;
|
||||
char *buffer;
|
||||
int modify;
|
||||
nv_cap_t *cap = NV_PDE_DATA(inode);
|
||||
|
||||
if (s != NULL)
|
||||
{
|
||||
private = s->private;
|
||||
}
|
||||
|
||||
up_read(&nv_system_pm_lock);
|
||||
|
||||
single_release(inode, file);
|
||||
|
||||
if (private != NULL)
|
||||
{
|
||||
buffer = private->buffer;
|
||||
|
||||
if (private->offset != 0)
|
||||
{
|
||||
if (sscanf(buffer, "DeviceFileModify: %d", &modify) == 1)
|
||||
{
|
||||
cap->modify = modify;
|
||||
}
|
||||
}
|
||||
|
||||
NV_KFREE(private, sizeof(nv_cap_file_private_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* All open files using the proc entry will be invalidated
|
||||
* if the entry is removed.
|
||||
*/
|
||||
file->private_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nv_proc_ops_t g_nv_cap_procfs_fops = {
|
||||
NV_PROC_OPS_SET_OWNER()
|
||||
.NV_PROC_OPS_OPEN = nv_cap_procfs_open,
|
||||
.NV_PROC_OPS_RELEASE = nv_cap_procfs_release,
|
||||
.NV_PROC_OPS_WRITE = nv_cap_procfs_write,
|
||||
.NV_PROC_OPS_READ = seq_read,
|
||||
.NV_PROC_OPS_LSEEK = seq_lseek,
|
||||
};
|
||||
|
||||
/* forward declaration of g_nv_cap_drv_fops */
|
||||
static struct file_operations g_nv_cap_drv_fops;
|
||||
|
||||
int NV_API_CALL nv_cap_validate_and_dup_fd(const nv_cap_t *cap, int fd)
|
||||
{
|
||||
struct file *file;
|
||||
int dup_fd;
|
||||
struct inode *inode = NULL;
|
||||
dev_t rdev = 0;
|
||||
struct files_struct *files = current->files;
|
||||
struct fdtable *fdt;
|
||||
|
||||
if (cap == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
file = fget(fd);
|
||||
if (file == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
inode = NV_FILE_INODE(file);
|
||||
if (inode == NULL)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Make sure the fd belongs to the nv-cap-drv */
|
||||
if (file->f_op != &g_nv_cap_drv_fops)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Make sure the fd has the expected capability */
|
||||
rdev = inode->i_rdev;
|
||||
if (MINOR(rdev) != cap->minor)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
dup_fd = NV_GET_UNUSED_FD_FLAGS(O_CLOEXEC);
|
||||
if (dup_fd < 0)
|
||||
{
|
||||
dup_fd = NV_GET_UNUSED_FD();
|
||||
if (dup_fd < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set CLOEXEC before installing the FD.
|
||||
*
|
||||
* If fork() happens in between, the opened unused FD will have
|
||||
* a NULL struct file associated with it, which is okay.
|
||||
*
|
||||
* The only well known bug here is the race with dup(2), which is
|
||||
* already documented in the kernel, see fd_install()'s description.
|
||||
*/
|
||||
|
||||
spin_lock(&files->file_lock);
|
||||
fdt = files_fdtable(files);
|
||||
__set_bit(dup_fd, fdt->close_on_exec);
|
||||
spin_unlock(&files->file_lock);
|
||||
}
|
||||
|
||||
fd_install(dup_fd, file);
|
||||
return dup_fd;
|
||||
|
||||
err:
|
||||
fput(file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_cap_close_fd(int fd)
|
||||
{
|
||||
if (fd == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Acquire task_lock as we access current->files explicitly (__close_fd)
|
||||
* and implicitly (sys_close), and it will race with the exit path.
|
||||
*/
|
||||
task_lock(current);
|
||||
|
||||
/* Nothing to do, we are in exit path */
|
||||
if (current->files == NULL)
|
||||
{
|
||||
task_unlock(current);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* From v4.17-rc1 (to v5.10.8) kernels have stopped exporting sys_close(fd)
|
||||
* and started exporting __close_fd, as of this commit:
|
||||
* 2018-04-02 2ca2a09d6215 ("fs: add ksys_close() wrapper; remove in-kernel
|
||||
* calls to sys_close()")
|
||||
* Kernels v5.11-rc1 onwards have stopped exporting __close_fd, and started
|
||||
* exporting close_fd, as of this commit:
|
||||
* 2020-12-20 8760c909f54a ("file: Rename __close_fd to close_fd and remove
|
||||
* the files parameter")
|
||||
*/
|
||||
#if NV_IS_EXPORT_SYMBOL_PRESENT_close_fd
|
||||
close_fd(fd);
|
||||
#elif NV_IS_EXPORT_SYMBOL_PRESENT___close_fd
|
||||
__close_fd(current->files, fd);
|
||||
#else
|
||||
sys_close(fd);
|
||||
#endif
|
||||
|
||||
task_unlock(current);
|
||||
}
|
||||
|
||||
static nv_cap_t* nv_cap_alloc(nv_cap_t *parent_cap, const char *name)
|
||||
{
|
||||
nv_cap_t *cap;
|
||||
int len;
|
||||
|
||||
if (parent_cap == NULL || name == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NV_KMALLOC(cap, sizeof(nv_cap_t));
|
||||
if (cap == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(name) + strlen(parent_cap->path) + 2;
|
||||
NV_KMALLOC(cap->path, len);
|
||||
if (cap->path == NULL)
|
||||
{
|
||||
NV_KFREE(cap, sizeof(nv_cap_t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(cap->path, parent_cap->path);
|
||||
strcat(cap->path, "/");
|
||||
strcat(cap->path, name);
|
||||
|
||||
len = strlen(name) + 1;
|
||||
NV_KMALLOC(cap->name, len);
|
||||
if (cap->name == NULL)
|
||||
{
|
||||
NV_KFREE(cap->path, strlen(cap->path) + 1);
|
||||
NV_KFREE(cap, sizeof(nv_cap_t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(cap->name, name);
|
||||
|
||||
cap->minor = -1;
|
||||
cap->modify = NVreg_ModifyDeviceFiles;
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
static void nv_cap_free(nv_cap_t *cap)
|
||||
{
|
||||
if (cap == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NV_KFREE(cap->path, strlen(cap->path) + 1);
|
||||
NV_KFREE(cap->name, strlen(cap->name) + 1);
|
||||
NV_KFREE(cap, sizeof(nv_cap_t));
|
||||
}
|
||||
|
||||
nv_cap_t* NV_API_CALL nv_cap_create_file_entry(nv_cap_t *parent_cap,
|
||||
const char *name, int mode)
|
||||
{
|
||||
nv_cap_t *cap = NULL;
|
||||
int minor;
|
||||
|
||||
cap = nv_cap_alloc(parent_cap, name);
|
||||
if (cap == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cap->parent = parent_cap->entry;
|
||||
cap->permissions = mode;
|
||||
|
||||
mode = (S_IFREG | S_IRUGO);
|
||||
|
||||
minor = nv_cap_find_minor(cap->path);
|
||||
if (minor < 0)
|
||||
{
|
||||
nv_cap_free(cap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cap->minor = minor;
|
||||
|
||||
cap->entry = proc_create_data(name, mode, parent_cap->entry,
|
||||
&g_nv_cap_procfs_fops, (void*)cap);
|
||||
if (cap->entry == NULL)
|
||||
{
|
||||
nv_cap_free(cap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
nv_cap_t* NV_API_CALL nv_cap_create_dir_entry(nv_cap_t *parent_cap,
|
||||
const char *name, int mode)
|
||||
{
|
||||
nv_cap_t *cap = NULL;
|
||||
|
||||
cap = nv_cap_alloc(parent_cap, name);
|
||||
if (cap == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cap->parent = parent_cap->entry;
|
||||
cap->permissions = mode;
|
||||
cap->minor = -1;
|
||||
|
||||
mode = (S_IFDIR | S_IRUGO | S_IXUGO);
|
||||
|
||||
cap->entry = NV_PROC_MKDIR_MODE(name, mode, parent_cap->entry);
|
||||
if (cap->entry == NULL)
|
||||
{
|
||||
nv_cap_free(cap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
nv_cap_t* NV_API_CALL nv_cap_init(const char *path)
|
||||
{
|
||||
nv_cap_t parent_cap;
|
||||
nv_cap_t *cap;
|
||||
int mode;
|
||||
char *name = NULL;
|
||||
char dir[] = "/capabilities";
|
||||
|
||||
if (path == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NV_KMALLOC(name, (strlen(path) + strlen(dir)) + 1);
|
||||
if (name == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(name, path);
|
||||
strcat(name, dir);
|
||||
parent_cap.entry = NULL;
|
||||
parent_cap.path = "";
|
||||
parent_cap.name = "";
|
||||
mode = S_IRUGO | S_IXUGO;
|
||||
cap = nv_cap_create_dir_entry(&parent_cap, name, mode);
|
||||
|
||||
NV_KFREE(name, strlen(name) + 1);
|
||||
return cap;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_cap_destroy_entry(nv_cap_t *cap)
|
||||
{
|
||||
if (WARN_ON(cap == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
remove_proc_entry(cap->name, cap->parent);
|
||||
nv_cap_free(cap);
|
||||
}
|
||||
|
||||
static int nv_cap_drv_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_cap_drv_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations g_nv_cap_drv_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = nv_cap_drv_open,
|
||||
.release = nv_cap_drv_release
|
||||
};
|
||||
|
||||
int NV_API_CALL nv_cap_drv_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
nv_cap_tables_init();
|
||||
|
||||
if (g_nv_cap_drv.initialized)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "nv-caps-drv is already initialized.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
rc = alloc_chrdev_region(&g_nv_cap_drv.devno,
|
||||
0,
|
||||
NV_CAP_DRV_MINOR_COUNT,
|
||||
"nvidia-caps");
|
||||
if (rc < 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "nv-caps-drv failed to create cdev region.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
cdev_init(&g_nv_cap_drv.cdev, &g_nv_cap_drv_fops);
|
||||
|
||||
g_nv_cap_drv.cdev.owner = THIS_MODULE;
|
||||
|
||||
rc = cdev_add(&g_nv_cap_drv.cdev, g_nv_cap_drv.devno,
|
||||
NV_CAP_DRV_MINOR_COUNT);
|
||||
if (rc < 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "nv-caps-drv failed to create cdev.\n");
|
||||
goto cdev_add_fail;
|
||||
}
|
||||
|
||||
rc = nv_cap_procfs_init();
|
||||
if (rc < 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "nv-caps-drv: unable to init proc\n");
|
||||
goto proc_init_fail;
|
||||
}
|
||||
|
||||
g_nv_cap_drv.initialized = NV_TRUE;
|
||||
|
||||
return 0;
|
||||
|
||||
proc_init_fail:
|
||||
cdev_del(&g_nv_cap_drv.cdev);
|
||||
|
||||
cdev_add_fail:
|
||||
unregister_chrdev_region(g_nv_cap_drv.devno, NV_CAP_DRV_MINOR_COUNT);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_cap_drv_exit(void)
|
||||
{
|
||||
if (!g_nv_cap_drv.initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nv_cap_procfs_exit();
|
||||
|
||||
cdev_del(&g_nv_cap_drv.cdev);
|
||||
|
||||
unregister_chrdev_region(g_nv_cap_drv.devno, NV_CAP_DRV_MINOR_COUNT);
|
||||
|
||||
g_nv_cap_drv.initialized = NV_FALSE;
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2011 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
#if defined(CONFIG_CRAY_XT)
|
||||
enum {
|
||||
NV_FORMAT_STATE_ORDINARY,
|
||||
NV_FORMAT_STATE_INTRODUCTION,
|
||||
NV_FORMAT_STATE_FLAGS,
|
||||
NV_FORMAT_STATE_FIELD_WIDTH,
|
||||
NV_FORMAT_STATE_PRECISION,
|
||||
NV_FORMAT_STATE_LENGTH_MODIFIER,
|
||||
NV_FORMAT_STATE_CONVERSION_SPECIFIER
|
||||
};
|
||||
|
||||
enum {
|
||||
NV_LENGTH_MODIFIER_NONE,
|
||||
NV_LENGTH_MODIFIER_CHAR,
|
||||
NV_LENGTH_MODIFIER_SHORT_INT,
|
||||
NV_LENGTH_MODIFIER_LONG_INT,
|
||||
NV_LENGTH_MODIFIER_LONG_LONG_INT
|
||||
};
|
||||
|
||||
#define NV_IS_FLAG(c) \
|
||||
((c) == '#' || (c) == '0' || (c) == '-' || (c) == ' ' || (c) == '+')
|
||||
#define NV_IS_LENGTH_MODIFIER(c) \
|
||||
((c) == 'h' || (c) == 'l' || (c) == 'L' || (c) == 'q' || (c) == 'j' || \
|
||||
(c) == 'z' || (c) == 't')
|
||||
#define NV_IS_CONVERSION_SPECIFIER(c) \
|
||||
((c) == 'd' || (c) == 'i' || (c) == 'o' || (c) == 'u' || (c) == 'x' || \
|
||||
(c) == 'X' || (c) == 'e' || (c) == 'E' || (c) == 'f' || (c) == 'F' || \
|
||||
(c) == 'g' || (c) == 'G' || (c) == 'a' || (c) == 'A' || (c) == 'c' || \
|
||||
(c) == 's' || (c) == 'p')
|
||||
|
||||
#define NV_MAX_NUM_INFO_MMRS 6
|
||||
|
||||
NV_STATUS nvos_forward_error_to_cray(
|
||||
struct pci_dev *dev,
|
||||
NvU32 error_number,
|
||||
const char *format,
|
||||
va_list ap
|
||||
)
|
||||
{
|
||||
NvU32 num_info_mmrs;
|
||||
NvU64 x = 0, info_mmrs[NV_MAX_NUM_INFO_MMRS];
|
||||
int state = NV_FORMAT_STATE_ORDINARY;
|
||||
int modifier = NV_LENGTH_MODIFIER_NONE;
|
||||
NvU32 i, n = 0, m = 0;
|
||||
|
||||
memset(info_mmrs, 0, sizeof(info_mmrs));
|
||||
while (*format != '\0')
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case NV_FORMAT_STATE_ORDINARY:
|
||||
if (*format == '%')
|
||||
state = NV_FORMAT_STATE_INTRODUCTION;
|
||||
break;
|
||||
case NV_FORMAT_STATE_INTRODUCTION:
|
||||
if (*format == '%')
|
||||
{
|
||||
state = NV_FORMAT_STATE_ORDINARY;
|
||||
break;
|
||||
}
|
||||
case NV_FORMAT_STATE_FLAGS:
|
||||
if (NV_IS_FLAG(*format))
|
||||
{
|
||||
state = NV_FORMAT_STATE_FLAGS;
|
||||
break;
|
||||
}
|
||||
else if (*format == '*')
|
||||
{
|
||||
state = NV_FORMAT_STATE_FIELD_WIDTH;
|
||||
break;
|
||||
}
|
||||
case NV_FORMAT_STATE_FIELD_WIDTH:
|
||||
if ((*format >= '0') && (*format <= '9'))
|
||||
{
|
||||
state = NV_FORMAT_STATE_FIELD_WIDTH;
|
||||
break;
|
||||
}
|
||||
else if (*format == '.')
|
||||
{
|
||||
state = NV_FORMAT_STATE_PRECISION;
|
||||
break;
|
||||
}
|
||||
case NV_FORMAT_STATE_PRECISION:
|
||||
if ((*format >= '0') && (*format <= '9'))
|
||||
{
|
||||
state = NV_FORMAT_STATE_PRECISION;
|
||||
break;
|
||||
}
|
||||
else if (NV_IS_LENGTH_MODIFIER(*format))
|
||||
{
|
||||
state = NV_FORMAT_STATE_LENGTH_MODIFIER;
|
||||
break;
|
||||
}
|
||||
else if (NV_IS_CONVERSION_SPECIFIER(*format))
|
||||
{
|
||||
state = NV_FORMAT_STATE_CONVERSION_SPECIFIER;
|
||||
break;
|
||||
}
|
||||
case NV_FORMAT_STATE_LENGTH_MODIFIER:
|
||||
if ((*format == 'h') || (*format == 'l'))
|
||||
{
|
||||
state = NV_FORMAT_STATE_LENGTH_MODIFIER;
|
||||
break;
|
||||
}
|
||||
else if (NV_IS_CONVERSION_SPECIFIER(*format))
|
||||
{
|
||||
state = NV_FORMAT_STATE_CONVERSION_SPECIFIER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (state)
|
||||
{
|
||||
case NV_FORMAT_STATE_INTRODUCTION:
|
||||
modifier = NV_LENGTH_MODIFIER_NONE;
|
||||
break;
|
||||
case NV_FORMAT_STATE_LENGTH_MODIFIER:
|
||||
switch (*format)
|
||||
{
|
||||
case 'h':
|
||||
modifier = (modifier == NV_LENGTH_MODIFIER_NONE)
|
||||
? NV_LENGTH_MODIFIER_SHORT_INT
|
||||
: NV_LENGTH_MODIFIER_CHAR;
|
||||
break;
|
||||
case 'l':
|
||||
modifier = (modifier == NV_LENGTH_MODIFIER_NONE)
|
||||
? NV_LENGTH_MODIFIER_LONG_INT
|
||||
: NV_LENGTH_MODIFIER_LONG_LONG_INT;
|
||||
break;
|
||||
case 'q':
|
||||
modifier = NV_LENGTH_MODIFIER_LONG_LONG_INT;
|
||||
default:
|
||||
return NV_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
break;
|
||||
case NV_FORMAT_STATE_CONVERSION_SPECIFIER:
|
||||
switch (*format)
|
||||
{
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'i':
|
||||
x = (unsigned int)va_arg(ap, int);
|
||||
break;
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
switch (modifier)
|
||||
{
|
||||
case NV_LENGTH_MODIFIER_LONG_LONG_INT:
|
||||
x = va_arg(ap, unsigned long long int);
|
||||
break;
|
||||
case NV_LENGTH_MODIFIER_LONG_INT:
|
||||
x = va_arg(ap, unsigned long int);
|
||||
break;
|
||||
case NV_LENGTH_MODIFIER_CHAR:
|
||||
case NV_LENGTH_MODIFIER_SHORT_INT:
|
||||
case NV_LENGTH_MODIFIER_NONE:
|
||||
x = va_arg(ap, unsigned int);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NV_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
state = NV_FORMAT_STATE_ORDINARY;
|
||||
for (i = 0; i < ((modifier == NV_LENGTH_MODIFIER_LONG_LONG_INT)
|
||||
? 2 : 1); i++)
|
||||
{
|
||||
if (m == NV_MAX_NUM_INFO_MMRS)
|
||||
return NV_ERR_INSUFFICIENT_RESOURCES;
|
||||
info_mmrs[m] = ((info_mmrs[m] << 32) | (x & 0xffffffff));
|
||||
x >>= 32;
|
||||
if (++n == 2)
|
||||
{
|
||||
m++;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
num_info_mmrs = (m + (n != 0));
|
||||
if (num_info_mmrs > 0)
|
||||
cray_nvidia_report_error(dev, error_number, num_info_mmrs, info_mmrs);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2012-2013 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-reg.h"
|
||||
#include "nv-frontend.h"
|
||||
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
|
||||
MODULE_INFO(supported, "external");
|
||||
MODULE_VERSION(NV_VERSION_STRING);
|
||||
MODULE_ALIAS_CHARDEV_MAJOR(NV_MAJOR_DEVICE_NUMBER);
|
||||
|
||||
/*
|
||||
* MODULE_IMPORT_NS() is added by commit id 8651ec01daeda
|
||||
* ("module: add support for symbol namespaces") in 5.4
|
||||
*/
|
||||
#if defined(MODULE_IMPORT_NS)
|
||||
|
||||
/*
|
||||
* DMA_BUF namespace is added by commit id 16b0314aa746
|
||||
* ("dma-buf: move dma-buf symbols into the DMA_BUF module namespace") in 5.16
|
||||
*/
|
||||
MODULE_IMPORT_NS(DMA_BUF);
|
||||
|
||||
#endif
|
||||
|
||||
static NvU32 nv_num_instances;
|
||||
|
||||
// lock required to protect table.
|
||||
struct semaphore nv_module_table_lock;
|
||||
|
||||
// minor number table
|
||||
nvidia_module_t *nv_minor_num_table[NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX + 1];
|
||||
|
||||
int nvidia_init_module(void);
|
||||
void nvidia_exit_module(void);
|
||||
|
||||
/* EXPORTS to Linux Kernel */
|
||||
|
||||
int nvidia_frontend_open(struct inode *, struct file *);
|
||||
int nvidia_frontend_close(struct inode *, struct file *);
|
||||
unsigned int nvidia_frontend_poll(struct file *, poll_table *);
|
||||
int nvidia_frontend_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
||||
long nvidia_frontend_unlocked_ioctl(struct file *, unsigned int, unsigned long);
|
||||
long nvidia_frontend_compat_ioctl(struct file *, unsigned int, unsigned long);
|
||||
int nvidia_frontend_mmap(struct file *, struct vm_area_struct *);
|
||||
|
||||
/* character driver entry points */
|
||||
static struct file_operations nv_frontend_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.poll = nvidia_frontend_poll,
|
||||
.unlocked_ioctl = nvidia_frontend_unlocked_ioctl,
|
||||
#if NVCPU_IS_X86_64 || NVCPU_IS_AARCH64
|
||||
.compat_ioctl = nvidia_frontend_compat_ioctl,
|
||||
#endif
|
||||
.mmap = nvidia_frontend_mmap,
|
||||
.open = nvidia_frontend_open,
|
||||
.release = nvidia_frontend_close,
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
static int add_device(nvidia_module_t *module, nv_linux_state_t *device, NvBool all)
|
||||
{
|
||||
NvU32 i;
|
||||
int rc = -1;
|
||||
|
||||
// look for free a minor number and assign unique minor number to this device
|
||||
for (i = 0; i <= NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN; i++)
|
||||
{
|
||||
if (nv_minor_num_table[i] == NULL)
|
||||
{
|
||||
nv_minor_num_table[i] = module;
|
||||
device->minor_num = i;
|
||||
if (all == NV_TRUE)
|
||||
{
|
||||
device = device->next;
|
||||
if (device == NULL)
|
||||
{
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int remove_device(nvidia_module_t *module, nv_linux_state_t *device)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
// remove this device from minor_number table
|
||||
if ((device != NULL) && (nv_minor_num_table[device->minor_num] != NULL))
|
||||
{
|
||||
nv_minor_num_table[device->minor_num] = NULL;
|
||||
device->minor_num = 0;
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Export functions */
|
||||
|
||||
int nvidia_register_module(nvidia_module_t *module)
|
||||
{
|
||||
int rc = 0;
|
||||
NvU32 ctrl_minor_num;
|
||||
|
||||
down(&nv_module_table_lock);
|
||||
if (module->instance >= NV_MAX_MODULE_INSTANCES)
|
||||
{
|
||||
printk("NVRM: NVIDIA module instance %d registration failed.\n",
|
||||
module->instance);
|
||||
rc = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ctrl_minor_num = NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - module->instance;
|
||||
nv_minor_num_table[ctrl_minor_num] = module;
|
||||
nv_num_instances++;
|
||||
done:
|
||||
up(&nv_module_table_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(nvidia_register_module);
|
||||
|
||||
int nvidia_unregister_module(nvidia_module_t *module)
|
||||
{
|
||||
int rc = 0;
|
||||
NvU32 ctrl_minor_num;
|
||||
|
||||
down(&nv_module_table_lock);
|
||||
|
||||
ctrl_minor_num = NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - module->instance;
|
||||
if (nv_minor_num_table[ctrl_minor_num] == NULL)
|
||||
{
|
||||
printk("NVRM: NVIDIA module for %d instance does not exist\n",
|
||||
module->instance);
|
||||
rc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nv_minor_num_table[ctrl_minor_num] = NULL;
|
||||
nv_num_instances--;
|
||||
}
|
||||
|
||||
up(&nv_module_table_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(nvidia_unregister_module);
|
||||
|
||||
int nvidia_frontend_add_device(nvidia_module_t *module, nv_linux_state_t * device)
|
||||
{
|
||||
int rc = -1;
|
||||
NvU32 ctrl_minor_num;
|
||||
|
||||
down(&nv_module_table_lock);
|
||||
ctrl_minor_num = NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - module->instance;
|
||||
if (nv_minor_num_table[ctrl_minor_num] == NULL)
|
||||
{
|
||||
printk("NVRM: NVIDIA module for %d instance does not exist\n",
|
||||
module->instance);
|
||||
rc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = add_device(module, device, NV_FALSE);
|
||||
}
|
||||
up(&nv_module_table_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(nvidia_frontend_add_device);
|
||||
|
||||
int nvidia_frontend_remove_device(nvidia_module_t *module, nv_linux_state_t * device)
|
||||
{
|
||||
int rc = 0;
|
||||
NvU32 ctrl_minor_num;
|
||||
|
||||
down(&nv_module_table_lock);
|
||||
ctrl_minor_num = NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - module->instance;
|
||||
if (nv_minor_num_table[ctrl_minor_num] == NULL)
|
||||
{
|
||||
printk("NVRM: NVIDIA module for %d instance does not exist\n",
|
||||
module->instance);
|
||||
rc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = remove_device(module, device);
|
||||
}
|
||||
up(&nv_module_table_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(nvidia_frontend_remove_device);
|
||||
|
||||
int nvidia_frontend_open(
|
||||
struct inode *inode,
|
||||
struct file *file
|
||||
)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
nvidia_module_t *module = NULL;
|
||||
|
||||
NvU32 minor_num = NV_FRONTEND_MINOR_NUMBER(inode);
|
||||
|
||||
down(&nv_module_table_lock);
|
||||
module = nv_minor_num_table[minor_num];
|
||||
|
||||
if ((module != NULL) && (module->open != NULL))
|
||||
{
|
||||
// Increment the reference count of module to ensure that module does
|
||||
// not get unloaded if its corresponding device file is open, for
|
||||
// example nvidiaN.ko should not get unloaded if /dev/nvidiaN is open.
|
||||
if (!try_module_get(module->owner))
|
||||
{
|
||||
up(&nv_module_table_lock);
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = module->open(inode, file);
|
||||
if (rc < 0)
|
||||
{
|
||||
module_put(module->owner);
|
||||
}
|
||||
}
|
||||
|
||||
up(&nv_module_table_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int nvidia_frontend_close(
|
||||
struct inode *inode,
|
||||
struct file *file
|
||||
)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
nvidia_module_t *module = NULL;
|
||||
|
||||
NvU32 minor_num = NV_FRONTEND_MINOR_NUMBER(inode);
|
||||
|
||||
module = nv_minor_num_table[minor_num];
|
||||
|
||||
if ((module != NULL) && (module->close != NULL))
|
||||
{
|
||||
rc = module->close(inode, file);
|
||||
|
||||
// Decrement the reference count of module.
|
||||
module_put(module->owner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned int nvidia_frontend_poll(
|
||||
struct file *file,
|
||||
poll_table *wait
|
||||
)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
struct inode *inode = NV_FILE_INODE(file);
|
||||
NvU32 minor_num = NV_FRONTEND_MINOR_NUMBER(inode);
|
||||
nvidia_module_t *module = nv_minor_num_table[minor_num];
|
||||
|
||||
if ((module != NULL) && (module->poll != NULL))
|
||||
mask = module->poll(file, wait);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
int nvidia_frontend_ioctl(
|
||||
struct inode *inode,
|
||||
struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long i_arg)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
nvidia_module_t *module = NULL;
|
||||
|
||||
NvU32 minor_num = NV_FRONTEND_MINOR_NUMBER(inode);
|
||||
module = nv_minor_num_table[minor_num];
|
||||
|
||||
if ((module != NULL) && (module->ioctl != NULL))
|
||||
rc = module->ioctl(inode, file, cmd, i_arg);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
long nvidia_frontend_unlocked_ioctl(
|
||||
struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long i_arg
|
||||
)
|
||||
{
|
||||
return nvidia_frontend_ioctl(NV_FILE_INODE(file), file, cmd, i_arg);
|
||||
}
|
||||
|
||||
long nvidia_frontend_compat_ioctl(
|
||||
struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long i_arg
|
||||
)
|
||||
{
|
||||
return nvidia_frontend_ioctl(NV_FILE_INODE(file), file, cmd, i_arg);
|
||||
}
|
||||
|
||||
int nvidia_frontend_mmap(
|
||||
struct file *file,
|
||||
struct vm_area_struct *vma
|
||||
)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
struct inode *inode = NV_FILE_INODE(file);
|
||||
NvU32 minor_num = NV_FRONTEND_MINOR_NUMBER(inode);
|
||||
nvidia_module_t *module = nv_minor_num_table[minor_num];
|
||||
|
||||
if ((module != NULL) && (module->mmap != NULL))
|
||||
rc = module->mmap(file, vma);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __init nvidia_frontend_init_module(void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
// initialise nvidia module table;
|
||||
nv_num_instances = 0;
|
||||
memset(nv_minor_num_table, 0, sizeof(nv_minor_num_table));
|
||||
NV_INIT_MUTEX(&nv_module_table_lock);
|
||||
|
||||
status = nvidia_init_module();
|
||||
if (status < 0)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// register char device
|
||||
status = register_chrdev(NV_MAJOR_DEVICE_NUMBER, "nvidia-frontend", &nv_frontend_fops);
|
||||
if (status < 0)
|
||||
{
|
||||
printk("NVRM: register_chrdev() failed!\n");
|
||||
nvidia_exit_module();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void __exit nvidia_frontend_exit_module(void)
|
||||
{
|
||||
/*
|
||||
* If this is the last nvidia_module to be unregistered, cleanup and
|
||||
* unregister char dev
|
||||
*/
|
||||
if (nv_num_instances == 1)
|
||||
{
|
||||
unregister_chrdev(NV_MAJOR_DEVICE_NUMBER, "nvidia-frontend");
|
||||
}
|
||||
|
||||
nvidia_exit_module();
|
||||
}
|
||||
|
||||
module_init(nvidia_frontend_init_module);
|
||||
module_exit(nvidia_frontend_exit_module);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2012-2013 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NV_FRONTEND_H_
|
||||
#define _NV_FRONTEND_H_
|
||||
|
||||
#include "nvtypes.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-register-module.h"
|
||||
|
||||
#define NV_MAX_MODULE_INSTANCES 8
|
||||
|
||||
#define NV_FRONTEND_MINOR_NUMBER(x) minor((x)->i_rdev)
|
||||
|
||||
#define NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX 255
|
||||
#define NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN (NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - \
|
||||
NV_MAX_MODULE_INSTANCES)
|
||||
|
||||
#define NV_FRONTEND_IS_CONTROL_DEVICE(x) ((x <= NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX) && \
|
||||
(x > NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN))
|
||||
|
||||
int nvidia_frontend_add_device(nvidia_module_t *, nv_linux_state_t *);
|
||||
int nvidia_frontend_remove_device(nvidia_module_t *, nv_linux_state_t *);
|
||||
|
||||
extern nvidia_module_t *nv_minor_num_table[];
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2005-2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
||||
static int nv_i2c_algo_master_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num)
|
||||
{
|
||||
nv_state_t *nv = (nv_state_t *)adapter->algo_data;
|
||||
unsigned int i = 0;
|
||||
int rc;
|
||||
NV_STATUS rmStatus = NV_OK;
|
||||
nvidia_stack_t *sp = NULL;
|
||||
const unsigned int supported_i2c_flags = I2C_M_RD
|
||||
#if defined(I2C_M_DMA_SAFE)
|
||||
| I2C_M_DMA_SAFE
|
||||
#endif
|
||||
;
|
||||
|
||||
rc = nv_kmem_cache_alloc_stack(&sp);
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = -EIO;
|
||||
|
||||
for (i = 0; ((i < (unsigned int)num) && (rmStatus == NV_OK)); i++)
|
||||
{
|
||||
if (msgs[i].flags & ~supported_i2c_flags)
|
||||
{
|
||||
/* we only support basic I2C reads/writes, reject any other commands */
|
||||
rc = -EINVAL;
|
||||
nv_printf(NV_DBG_ERRORS, "NVRM: Unsupported I2C flags used. (flags:0x%08x)\n",
|
||||
msgs[i].flags);
|
||||
rmStatus = NV_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
(msgs[i].flags & I2C_M_RD) ?
|
||||
NV_I2C_CMD_READ : NV_I2C_CMD_WRITE,
|
||||
(NvU8)(msgs[i].addr & 0x7f), 0,
|
||||
(NvU32)(msgs[i].len & 0xffffUL),
|
||||
(NvU8 *)msgs[i].buf);
|
||||
}
|
||||
}
|
||||
|
||||
nv_kmem_cache_free_stack(sp);
|
||||
|
||||
return (rmStatus != NV_OK) ? rc : num;
|
||||
}
|
||||
|
||||
static int nv_i2c_algo_smbus_xfer(
|
||||
struct i2c_adapter *adapter,
|
||||
u16 addr,
|
||||
unsigned short flags,
|
||||
char read_write,
|
||||
u8 command,
|
||||
int size,
|
||||
union i2c_smbus_data *data
|
||||
)
|
||||
{
|
||||
nv_state_t *nv = (nv_state_t *)adapter->algo_data;
|
||||
int rc;
|
||||
NV_STATUS rmStatus = NV_OK;
|
||||
nvidia_stack_t *sp = NULL;
|
||||
|
||||
rc = nv_kmem_cache_alloc_stack(&sp);
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = -EIO;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case I2C_SMBUS_QUICK:
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
(read_write == I2C_SMBUS_READ) ?
|
||||
NV_I2C_CMD_SMBUS_QUICK_READ :
|
||||
NV_I2C_CMD_SMBUS_QUICK_WRITE,
|
||||
(NvU8)(addr & 0x7f), 0, 0, NULL);
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
{
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
NV_I2C_CMD_READ,
|
||||
(NvU8)(addr & 0x7f), 0, 1,
|
||||
(NvU8 *)&data->byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 data = command;
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
NV_I2C_CMD_WRITE,
|
||||
(NvU8)(addr & 0x7f), 0, 1,
|
||||
(NvU8 *)&data);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
(read_write == I2C_SMBUS_READ) ?
|
||||
NV_I2C_CMD_SMBUS_READ :
|
||||
NV_I2C_CMD_SMBUS_WRITE,
|
||||
(NvU8)(addr & 0x7f), (NvU8)command, 1,
|
||||
(NvU8 *)&data->byte);
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
if (read_write != I2C_SMBUS_READ)
|
||||
{
|
||||
u16 word = data->word;
|
||||
data->block[1] = (word & 0xff);
|
||||
data->block[2] = (word >> 8);
|
||||
}
|
||||
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
(read_write == I2C_SMBUS_READ) ?
|
||||
NV_I2C_CMD_SMBUS_READ :
|
||||
NV_I2C_CMD_SMBUS_WRITE,
|
||||
(NvU8)(addr & 0x7f), (NvU8)command, 2,
|
||||
(NvU8 *)&data->block[1]);
|
||||
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
{
|
||||
data->word = ((NvU16)data->block[1]) |
|
||||
((NvU16)data->block[2] << 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
(read_write == I2C_SMBUS_READ) ?
|
||||
NV_I2C_CMD_SMBUS_BLOCK_READ :
|
||||
NV_I2C_CMD_SMBUS_BLOCK_WRITE,
|
||||
(NvU8)(addr & 0x7f), (NvU8)command,
|
||||
sizeof(data->block),
|
||||
(NvU8 *)data->block);
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
rmStatus = rm_i2c_transfer(sp, nv, (void *)adapter,
|
||||
(read_write == I2C_SMBUS_READ) ?
|
||||
NV_I2C_CMD_BLOCK_READ :
|
||||
NV_I2C_CMD_BLOCK_WRITE,
|
||||
(NvU8)(addr & 0x7f), (NvU8)command,
|
||||
(NvU8)data->block[0],
|
||||
(NvU8 *)&data->block[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
rmStatus = NV_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
nv_kmem_cache_free_stack(sp);
|
||||
|
||||
return (rmStatus != NV_OK) ? rc : 0;
|
||||
}
|
||||
|
||||
static u32 nv_i2c_algo_functionality(struct i2c_adapter *adapter)
|
||||
{
|
||||
nv_state_t *nv = (nv_state_t *)adapter->algo_data;
|
||||
u32 ret = I2C_FUNC_I2C;
|
||||
nvidia_stack_t *sp = NULL;
|
||||
|
||||
if (nv_kmem_cache_alloc_stack(&sp) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rm_i2c_is_smbus_capable(sp, nv, adapter))
|
||||
{
|
||||
ret |= (I2C_FUNC_SMBUS_QUICK |
|
||||
I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA |
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK);
|
||||
}
|
||||
|
||||
nv_kmem_cache_free_stack(sp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm nv_i2c_algo = {
|
||||
.master_xfer = nv_i2c_algo_master_xfer,
|
||||
.smbus_xfer = nv_i2c_algo_smbus_xfer,
|
||||
.functionality = nv_i2c_algo_functionality,
|
||||
};
|
||||
|
||||
struct i2c_adapter nv_i2c_adapter_prototype = {
|
||||
.owner = THIS_MODULE,
|
||||
.algo = &nv_i2c_algo,
|
||||
.algo_data = NULL,
|
||||
};
|
||||
|
||||
void* NV_API_CALL nv_i2c_add_adapter(nv_state_t *nv, NvU32 port)
|
||||
{
|
||||
NV_STATUS rmStatus;
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
struct i2c_adapter *pI2cAdapter = NULL;
|
||||
int osstatus = 0;
|
||||
|
||||
// get a i2c adapter
|
||||
rmStatus = os_alloc_mem((void **)&pI2cAdapter,sizeof(struct i2c_adapter));
|
||||
|
||||
if (rmStatus != NV_OK)
|
||||
return NULL;
|
||||
|
||||
// fill in with default structure
|
||||
os_mem_copy(pI2cAdapter, &nv_i2c_adapter_prototype, sizeof(struct i2c_adapter));
|
||||
|
||||
pI2cAdapter->dev.parent = nvl->dev;
|
||||
|
||||
if (nvl->pci_dev != NULL)
|
||||
{
|
||||
snprintf(pI2cAdapter->name, sizeof(pI2cAdapter->name),
|
||||
"NVIDIA i2c adapter %u at %x:%02x.%u", port, nv->pci_info.bus,
|
||||
nv->pci_info.slot, PCI_FUNC(nvl->pci_dev->devfn));
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(pI2cAdapter->name, sizeof(pI2cAdapter->name),
|
||||
"NVIDIA SOC i2c adapter %u", port);
|
||||
}
|
||||
|
||||
// add our data to the structure
|
||||
pI2cAdapter->algo_data = (void *)nv;
|
||||
|
||||
// attempt to register with the kernel
|
||||
osstatus = i2c_add_adapter(pI2cAdapter);
|
||||
|
||||
if (osstatus)
|
||||
{
|
||||
// free the memory and NULL the ptr
|
||||
os_free_mem(pI2cAdapter);
|
||||
|
||||
pI2cAdapter = NULL;
|
||||
}
|
||||
|
||||
return ((void *)pI2cAdapter);
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_i2c_del_adapter(nv_state_t *nv, void *data)
|
||||
{
|
||||
struct i2c_adapter *pI2cAdapter = (struct i2c_adapter *)data;
|
||||
|
||||
if (pI2cAdapter)
|
||||
{
|
||||
// release with the OS
|
||||
i2c_del_adapter(pI2cAdapter);
|
||||
os_free_mem(pI2cAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
#else // defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
|
||||
void NV_API_CALL nv_i2c_del_adapter(nv_state_t *nv, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
void* NV_API_CALL nv_i2c_add_adapter(nv_state_t *nv, NvU32 port)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nv-ibmnpu.c - interface with the ibmnpu (IBM NVLink Processing Unit) "module"
|
||||
*/
|
||||
#include "nv-linux.h"
|
||||
|
||||
#if defined(NVCPU_PPC64LE)
|
||||
#include "nv-ibmnpu.h"
|
||||
#include "nv-rsync.h"
|
||||
|
||||
/*
|
||||
* Temporary query to get the L1D cache block size directly from the device
|
||||
* tree for the offline cache flush workaround, since the ppc64_caches symbol
|
||||
* is unavailable to us.
|
||||
*/
|
||||
const NvU32 P9_L1D_CACHE_DEFAULT_BLOCK_SIZE = 0x80;
|
||||
|
||||
static NvU32 nv_ibm_get_cpu_l1d_cache_block_size(void)
|
||||
{
|
||||
const __be32 *block_size_prop;
|
||||
|
||||
/*
|
||||
* Attempt to look up the block size from device tree. If unavailable, just
|
||||
* return the default that we see on these systems.
|
||||
*/
|
||||
struct device_node *cpu = of_find_node_by_type(NULL, "cpu");
|
||||
if (!cpu)
|
||||
{
|
||||
return P9_L1D_CACHE_DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
block_size_prop = of_get_property(cpu, "d-cache-block-size", NULL);
|
||||
if (!block_size_prop)
|
||||
{
|
||||
return P9_L1D_CACHE_DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
return be32_to_cpu(*block_size_prop);
|
||||
}
|
||||
|
||||
/*
|
||||
* GPU device memory can be exposed to the kernel as NUMA node memory via the
|
||||
* IBMNPU devices associated with the GPU. The platform firmware will specify
|
||||
* the parameters of where the memory lives in the system address space via
|
||||
* firmware properties on the IBMNPU devices. These properties specify what
|
||||
* memory can be accessed through the IBMNPU device, and the driver can online
|
||||
* a GPU device's memory into the range accessible by its associated IBMNPU
|
||||
* devices.
|
||||
*
|
||||
* This function calls over to the IBMNPU driver to query the parameters from
|
||||
* firmware, and validates that the resulting parameters are acceptable.
|
||||
*/
|
||||
static void nv_init_ibmnpu_numa_info(nv_state_t *nv)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
nv_npu_numa_info_t *npu_numa_info = &nvl->npu->numa_info;
|
||||
struct pci_dev *npu_dev = nvl->npu->devs[0];
|
||||
NvU64 spa, gpa, aper_size;
|
||||
|
||||
/*
|
||||
* Terminology:
|
||||
* - system physical address (spa): 47-bit NVIDIA physical address, which
|
||||
* is the CPU real address with the NVLink address compression scheme
|
||||
* already applied in firmware.
|
||||
* - guest physical address (gpa): 56-bit physical address as seen by the
|
||||
* operating system. This is the base address that we should use for
|
||||
* onlining device memory.
|
||||
*/
|
||||
nvl->numa_info.node_id = ibmnpu_device_get_memory_config(npu_dev, &spa, &gpa,
|
||||
&aper_size);
|
||||
if (nvl->numa_info.node_id == NUMA_NO_NODE)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv, "No NUMA memory aperture found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validate that the compressed system physical address is not too wide */
|
||||
if (spa & (~(BIT_ULL(nv_volta_dma_addr_size) - 1)))
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv,
|
||||
"Invalid NUMA memory system pa 0x%llx"
|
||||
" on IBM-NPU device %04x:%02x:%02x.%u\n",
|
||||
spa, NV_PCI_DOMAIN_NUMBER(npu_dev), NV_PCI_BUS_NUMBER(npu_dev),
|
||||
NV_PCI_SLOT_NUMBER(npu_dev), PCI_FUNC(npu_dev->devfn));
|
||||
goto invalid_numa_config;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that the guest physical address is aligned to 128GB.
|
||||
* This alignment requirement comes from the Volta address space
|
||||
* size on POWER9.
|
||||
*/
|
||||
if (!IS_ALIGNED(gpa, BIT_ULL(nv_volta_addr_space_width)))
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv,
|
||||
"Invalid alignment in NUMA memory guest pa 0x%llx"
|
||||
" on IBM-NPU device %04x:%02x:%02x.%u\n",
|
||||
gpa, NV_PCI_DOMAIN_NUMBER(npu_dev), NV_PCI_BUS_NUMBER(npu_dev),
|
||||
NV_PCI_SLOT_NUMBER(npu_dev), PCI_FUNC(npu_dev->devfn));
|
||||
goto invalid_numa_config;
|
||||
}
|
||||
|
||||
/* Validate that the aperture can map all of the device's framebuffer */
|
||||
if (aper_size < nv->fb->size)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv,
|
||||
"Insufficient NUMA memory aperture size 0x%llx"
|
||||
" on IBM-NPU device %04x:%02x:%02x.%u (0x%llx required)\n",
|
||||
aper_size, NV_PCI_DOMAIN_NUMBER(npu_dev),
|
||||
NV_PCI_BUS_NUMBER(npu_dev), NV_PCI_SLOT_NUMBER(npu_dev),
|
||||
PCI_FUNC(npu_dev->devfn), nv->fb->size);
|
||||
goto invalid_numa_config;
|
||||
}
|
||||
|
||||
npu_numa_info->compr_sys_phys_addr = spa;
|
||||
npu_numa_info->guest_phys_addr = gpa;
|
||||
|
||||
if (NVreg_EnableUserNUMAManagement)
|
||||
{
|
||||
NV_ATOMIC_SET(nvl->numa_info.status, NV_IOCTL_NUMA_STATUS_OFFLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv, "User-mode NUMA onlining disabled.\n");
|
||||
nvl->numa_info.node_id = NUMA_NO_NODE;
|
||||
}
|
||||
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv, "NUMA memory aperture: "
|
||||
"[spa = 0x%llx, gpa = 0x%llx, aper_size = 0x%llx]\n",
|
||||
spa, gpa, aper_size);
|
||||
|
||||
/* Get the CPU's L1D cache block size for offlining cache flush */
|
||||
npu_numa_info->l1d_cache_block_size = nv_ibm_get_cpu_l1d_cache_block_size();
|
||||
|
||||
return;
|
||||
|
||||
invalid_numa_config:
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv,
|
||||
"NUMA memory aperture disabled due to invalid firmware configuration\n");
|
||||
nvl->numa_info.node_id = NUMA_NO_NODE;
|
||||
}
|
||||
|
||||
void nv_init_ibmnpu_info(nv_state_t *nv)
|
||||
{
|
||||
#if defined(NV_PNV_PCI_GET_NPU_DEV_PRESENT)
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
struct pci_dev *npu_dev = pnv_pci_get_npu_dev(nvl->pci_dev, 0);
|
||||
NvU8 dev_count;
|
||||
|
||||
if (!npu_dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_alloc_mem((void **)&nvl->npu, sizeof(nv_ibmnpu_info_t)) != NV_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
os_mem_set(nvl->npu, 0, sizeof(nv_ibmnpu_info_t));
|
||||
|
||||
/* Find any other IBMNPU devices attached to this GPU */
|
||||
for (nvl->npu->devs[0] = npu_dev, dev_count = 1;
|
||||
dev_count < NV_MAX_ATTACHED_IBMNPUS; dev_count++)
|
||||
{
|
||||
nvl->npu->devs[dev_count] = pnv_pci_get_npu_dev(nvl->pci_dev, dev_count);
|
||||
if (!nvl->npu->devs[dev_count])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nvl->npu->dev_count = dev_count;
|
||||
|
||||
/*
|
||||
* If we run out of space for IBMNPU devices, NV_MAX_ATTACHED_IBMNPUS will
|
||||
* need to be bumped.
|
||||
*/
|
||||
WARN_ON((dev_count == NV_MAX_ATTACHED_IBMNPUS) &&
|
||||
pnv_pci_get_npu_dev(nvl->pci_dev, dev_count));
|
||||
|
||||
ibmnpu_device_get_genregs_info(npu_dev, &nvl->npu->genregs);
|
||||
|
||||
if (nvl->npu->genregs.size > 0)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv,
|
||||
"IBM-NPU device %04x:%02x:%02x.%u associated with GPU "
|
||||
" has a generation register space 0x%llx-0x%llx\n",
|
||||
NV_PCI_DOMAIN_NUMBER(npu_dev), NV_PCI_BUS_NUMBER(npu_dev),
|
||||
NV_PCI_SLOT_NUMBER(npu_dev), PCI_FUNC(npu_dev->devfn),
|
||||
nvl->npu->genregs.start_addr,
|
||||
nvl->npu->genregs.start_addr + nvl->npu->genregs.size - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv,
|
||||
"IBM-NPU device %04x:%02x:%02x.%u associated with GPU "
|
||||
"does not support generation registers\n",
|
||||
NV_PCI_DOMAIN_NUMBER(npu_dev), NV_PCI_BUS_NUMBER(npu_dev),
|
||||
NV_PCI_SLOT_NUMBER(npu_dev), PCI_FUNC(npu_dev->devfn));
|
||||
}
|
||||
|
||||
nv_init_ibmnpu_numa_info(nv);
|
||||
#endif
|
||||
}
|
||||
|
||||
void nv_destroy_ibmnpu_info(nv_state_t *nv)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (nvl->npu != NULL)
|
||||
{
|
||||
os_free_mem(nvl->npu);
|
||||
nvl->npu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int nv_init_ibmnpu_devices(nv_state_t *nv)
|
||||
{
|
||||
NvU8 i;
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (!nvl->npu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nvl->npu->dev_count; i++)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv,
|
||||
"Initializing IBM-NPU device %04x:%02x:%02x.%u\n",
|
||||
NV_PCI_DOMAIN_NUMBER(nvl->npu->devs[i]),
|
||||
NV_PCI_BUS_NUMBER(nvl->npu->devs[i]),
|
||||
NV_PCI_SLOT_NUMBER(nvl->npu->devs[i]),
|
||||
PCI_FUNC(nvl->npu->devs[i]->devfn));
|
||||
|
||||
if (ibmnpu_init_device(nvl->npu->devs[i]) != NVL_SUCCESS)
|
||||
{
|
||||
nv_unregister_ibmnpu_devices(nv);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
nvl->npu->initialized_dev_count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv_unregister_ibmnpu_devices(nv_state_t *nv)
|
||||
{
|
||||
NvU8 i;
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (!nvl->npu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nvl->npu->initialized_dev_count; i++)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_SETUP, nv,
|
||||
"Unregistering IBM-NPU device %04x:%02x:%02x.%u\n",
|
||||
NV_PCI_DOMAIN_NUMBER(nvl->npu->devs[i]),
|
||||
NV_PCI_BUS_NUMBER(nvl->npu->devs[i]),
|
||||
NV_PCI_SLOT_NUMBER(nvl->npu->devs[i]),
|
||||
PCI_FUNC(nvl->npu->devs[i]->devfn));
|
||||
|
||||
ibmnpu_unregister_device(nvl->npu->devs[i]);
|
||||
}
|
||||
|
||||
nvl->npu->initialized_dev_count = 0;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_get_ibmnpu_genreg_info(nv_state_t *nv, NvU64 *addr,
|
||||
NvU64 *size, void **device)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (nvl->npu == NULL || nvl->npu->genregs.size == 0)
|
||||
{
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
{
|
||||
*addr = nvl->npu->genregs.start_addr;
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
*size = nvl->npu->genregs.size;
|
||||
}
|
||||
|
||||
if (device)
|
||||
{
|
||||
*device = (void*)nvl->npu->devs[0];
|
||||
}
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_get_ibmnpu_relaxed_ordering_mode(nv_state_t *nv,
|
||||
NvBool *mode)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (nvl->npu == NULL || nvl->npu->genregs.size == 0)
|
||||
{
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
*mode = nv_get_rsync_relaxed_ordering_mode(nv);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_wait_for_ibmnpu_rsync(nv_state_t *nv)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (nvl->npu == NULL || nvl->npu->genregs.size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nv_wait_for_rsync(nv);
|
||||
}
|
||||
|
||||
int nv_get_ibmnpu_chip_id(nv_state_t *nv)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
if (nvl->npu == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ibmnpu_device_get_chip_id(nvl->npu->devs[0]);
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_ibmnpu_cache_flush_range(nv_state_t *nv, NvU64 cpu_virtual, NvU64 size)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
NvU64 offset, cbsize;
|
||||
|
||||
/*
|
||||
* The range is commonly an ioremap()ed mapping of the GPU's ATS range and
|
||||
* needs to be compared against the created mappings. Alternatively, kernel
|
||||
* page tables can be dumped through sysfs if CONFIG_PPC_PTDUMP is enabled.
|
||||
*/
|
||||
NV_DEV_PRINTF(NV_DBG_INFO, nv,
|
||||
"Flushing CPU virtual range [0x%llx, 0x%llx)\n",
|
||||
cpu_virtual, cpu_virtual + size);
|
||||
|
||||
cbsize = nvl->npu->numa_info.l1d_cache_block_size;
|
||||
|
||||
CACHE_FLUSH();
|
||||
|
||||
/* Force eviction of any cache lines from the NUMA-onlined region. */
|
||||
for (offset = 0; offset < size; offset += cbsize)
|
||||
{
|
||||
asm volatile("dcbf %0,%1" :: "r" (cpu_virtual), "r" (offset) : "memory");
|
||||
|
||||
/* Reschedule if necessary to avoid lockup warnings */
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
CACHE_FLUSH();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void nv_init_ibmnpu_info(nv_state_t *nv)
|
||||
{
|
||||
}
|
||||
|
||||
void nv_destroy_ibmnpu_info(nv_state_t *nv)
|
||||
{
|
||||
}
|
||||
|
||||
int nv_init_ibmnpu_devices(nv_state_t *nv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv_unregister_ibmnpu_devices(nv_state_t *nv)
|
||||
{
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_get_ibmnpu_genreg_info(nv_state_t *nv, NvU64 *addr,
|
||||
NvU64 *size, void **device)
|
||||
{
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_get_ibmnpu_relaxed_ordering_mode(nv_state_t *nv,
|
||||
NvBool *mode)
|
||||
{
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_wait_for_ibmnpu_rsync(nv_state_t *nv)
|
||||
{
|
||||
}
|
||||
|
||||
int nv_get_ibmnpu_chip_id(nv_state_t *nv)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_ibmnpu_cache_flush_range(nv_state_t *nv, NvU64 virtual, NvU64 size)
|
||||
{
|
||||
}
|
||||
|
||||
void nv_ibmnpu_cache_flush_numa_region(nv_state_t *nv)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NV_IBMNPU_H_
|
||||
#define _NV_IBMNPU_H_
|
||||
|
||||
#if defined(NVCPU_PPC64LE)
|
||||
|
||||
#include "ibmnpu_linux.h"
|
||||
|
||||
#define NV_MAX_ATTACHED_IBMNPUS 6
|
||||
|
||||
typedef struct nv_npu_numa_info
|
||||
{
|
||||
/*
|
||||
* 47-bit NVIDIA 'system physical address': the hypervisor real 56-bit
|
||||
* address with NVLink address compression scheme applied.
|
||||
*/
|
||||
NvU64 compr_sys_phys_addr;
|
||||
|
||||
/*
|
||||
* 56-bit NVIDIA 'guest physical address'/host virtual address. On
|
||||
* unvirtualized systems, applying the NVLink address compression scheme
|
||||
* to this address should be the same as compr_sys_phys_addr.
|
||||
*/
|
||||
NvU64 guest_phys_addr;
|
||||
|
||||
/*
|
||||
* L1 data cache block size on P9 - needed to manually flush/invalidate the
|
||||
* NUMA region from the CPU caches after offlining.
|
||||
*/
|
||||
NvU32 l1d_cache_block_size;
|
||||
} nv_npu_numa_info_t;
|
||||
|
||||
struct nv_ibmnpu_info
|
||||
{
|
||||
NvU8 dev_count;
|
||||
NvU8 initialized_dev_count;
|
||||
struct pci_dev *devs[NV_MAX_ATTACHED_IBMNPUS];
|
||||
ibmnpu_genregs_info_t genregs;
|
||||
nv_npu_numa_info_t numa_info;
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: These parameters are specific to Volta/P9 configurations, and may
|
||||
* need to be determined dynamically in the future.
|
||||
*/
|
||||
static const NvU32 nv_volta_addr_space_width = 37;
|
||||
static const NvU32 nv_volta_dma_addr_size = 47;
|
||||
|
||||
#endif
|
||||
|
||||
void nv_init_ibmnpu_info(nv_state_t *nv);
|
||||
void nv_destroy_ibmnpu_info(nv_state_t *nv);
|
||||
int nv_init_ibmnpu_devices(nv_state_t *nv);
|
||||
void nv_unregister_ibmnpu_devices(nv_state_t *nv);
|
||||
int nv_get_ibmnpu_chip_id(nv_state_t *nv);
|
||||
void nv_ibmnpu_cache_flush_numa_region(nv_state_t *nv);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2016 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nv-kthread-q.h"
|
||||
#include "nv-list-helpers.h"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#if defined(NV_LINUX_BUG_H_PRESENT)
|
||||
#include <linux/bug.h>
|
||||
#else
|
||||
#include <asm/bug.h>
|
||||
#endif
|
||||
|
||||
// Today's implementation is a little simpler and more limited than the
|
||||
// API description allows for in nv-kthread-q.h. Details include:
|
||||
//
|
||||
// 1. Each nv_kthread_q instance is a first-in, first-out queue.
|
||||
//
|
||||
// 2. Each nv_kthread_q instance is serviced by exactly one kthread.
|
||||
//
|
||||
// You can create any number of queues, each of which gets its own
|
||||
// named kernel thread (kthread). You can then insert arbitrary functions
|
||||
// into the queue, and those functions will be run in the context of the
|
||||
// queue's kthread.
|
||||
|
||||
#ifndef WARN
|
||||
// Only *really* old kernels (2.6.9) end up here. Just use a simple printk
|
||||
// to implement this, because such kernels won't be supported much longer.
|
||||
#define WARN(condition, format...) ({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
printk(KERN_ERR format); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define NVQ_WARN(fmt, ...) \
|
||||
do { \
|
||||
if (in_interrupt()) { \
|
||||
WARN(1, "nv_kthread_q: [in interrupt]: " fmt, \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
else { \
|
||||
WARN(1, "nv_kthread_q: task: %s: " fmt, \
|
||||
current->comm, \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int _main_loop(void *args)
|
||||
{
|
||||
nv_kthread_q_t *q = (nv_kthread_q_t *)args;
|
||||
nv_kthread_q_item_t *q_item = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
while (1) {
|
||||
// Normally this thread is never interrupted. However,
|
||||
// down_interruptible (instead of down) is called here,
|
||||
// in order to avoid being classified as a potentially
|
||||
// hung task, by the kernel watchdog.
|
||||
while (down_interruptible(&q->q_sem))
|
||||
NVQ_WARN("Interrupted during semaphore wait\n");
|
||||
|
||||
if (atomic_read(&q->main_loop_should_exit))
|
||||
break;
|
||||
|
||||
spin_lock_irqsave(&q->q_lock, flags);
|
||||
|
||||
// The q_sem semaphore prevents us from getting here unless there is
|
||||
// at least one item in the list, so an empty list indicates a bug.
|
||||
if (unlikely(list_empty(&q->q_list_head))) {
|
||||
spin_unlock_irqrestore(&q->q_lock, flags);
|
||||
NVQ_WARN("_main_loop: Empty queue: q: 0x%p\n", q);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Consume one item from the queue
|
||||
q_item = list_first_entry(&q->q_list_head,
|
||||
nv_kthread_q_item_t,
|
||||
q_list_node);
|
||||
|
||||
list_del_init(&q_item->q_list_node);
|
||||
|
||||
spin_unlock_irqrestore(&q->q_lock, flags);
|
||||
|
||||
// Run the item
|
||||
q_item->function_to_run(q_item->function_args);
|
||||
|
||||
// Make debugging a little simpler by clearing this between runs:
|
||||
q_item = NULL;
|
||||
}
|
||||
|
||||
while (!kthread_should_stop())
|
||||
schedule();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv_kthread_q_stop(nv_kthread_q_t *q)
|
||||
{
|
||||
// check if queue has been properly initialized
|
||||
if (unlikely(!q->q_kthread))
|
||||
return;
|
||||
|
||||
nv_kthread_q_flush(q);
|
||||
|
||||
// If this assertion fires, then a caller likely either broke the API rules,
|
||||
// by adding items after calling nv_kthread_q_stop, or possibly messed up
|
||||
// with inadequate flushing of self-rescheduling q_items.
|
||||
if (unlikely(!list_empty(&q->q_list_head)))
|
||||
NVQ_WARN("list not empty after flushing\n");
|
||||
|
||||
if (likely(!atomic_read(&q->main_loop_should_exit))) {
|
||||
|
||||
atomic_set(&q->main_loop_should_exit, 1);
|
||||
|
||||
// Wake up the kthread so that it can see that it needs to stop:
|
||||
up(&q->q_sem);
|
||||
|
||||
kthread_stop(q->q_kthread);
|
||||
q->q_kthread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// When CONFIG_VMAP_STACK is defined, the kernel thread stack allocator used by
|
||||
// kthread_create_on_node relies on a 2 entry, per-core cache to minimize
|
||||
// vmalloc invocations. The cache is NUMA-unaware, so when there is a hit, the
|
||||
// stack location ends up being a function of the core assigned to the current
|
||||
// thread, instead of being a function of the specified NUMA node. The cache was
|
||||
// added to the kernel in commit ac496bf48d97f2503eaa353996a4dd5e4383eaf0
|
||||
// ("fork: Optimize task creation by caching two thread stacks per CPU if
|
||||
// CONFIG_VMAP_STACK=y")
|
||||
//
|
||||
// To work around the problematic cache, we create up to three kernel threads
|
||||
// -If the first thread's stack is resident on the preferred node, return this
|
||||
// thread.
|
||||
// -Otherwise, create a second thread. If its stack is resident on the
|
||||
// preferred node, stop the first thread and return this one.
|
||||
// -Otherwise, create a third thread. The stack allocator does not find a
|
||||
// cached stack, and so falls back to vmalloc, which takes the NUMA hint into
|
||||
// consideration. The first two threads are then stopped.
|
||||
//
|
||||
// When CONFIG_VMAP_STACK is not defined, the first kernel thread is returned.
|
||||
//
|
||||
// This function is never invoked when there is no NUMA preference (preferred
|
||||
// node is NUMA_NO_NODE).
|
||||
static struct task_struct *thread_create_on_node(int (*threadfn)(void *data),
|
||||
nv_kthread_q_t *q,
|
||||
int preferred_node,
|
||||
const char *q_name)
|
||||
{
|
||||
|
||||
unsigned i, j;
|
||||
const static unsigned attempts = 3;
|
||||
struct task_struct *thread[3];
|
||||
|
||||
for (i = 0;; i++) {
|
||||
struct page *stack;
|
||||
|
||||
thread[i] = kthread_create_on_node(threadfn, q, preferred_node, q_name);
|
||||
|
||||
if (unlikely(IS_ERR(thread[i]))) {
|
||||
|
||||
// Instead of failing, pick the previous thread, even if its
|
||||
// stack is not allocated on the preferred node.
|
||||
if (i > 0)
|
||||
i--;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// vmalloc is not used to allocate the stack, so simply return the
|
||||
// thread, even if its stack may not be allocated on the preferred node
|
||||
if (!is_vmalloc_addr(thread[i]->stack))
|
||||
break;
|
||||
|
||||
// Ran out of attempts - return thread even if its stack may not be
|
||||
// allocated on the preferred node
|
||||
if ((i == (attempts - 1)))
|
||||
break;
|
||||
|
||||
// Get the NUMA node where the first page of the stack is resident. If
|
||||
// it is the preferred node, select this thread.
|
||||
stack = vmalloc_to_page(thread[i]->stack);
|
||||
if (page_to_nid(stack) == preferred_node)
|
||||
break;
|
||||
}
|
||||
|
||||
for (j = i; j > 0; j--)
|
||||
kthread_stop(thread[j - 1]);
|
||||
|
||||
return thread[i];
|
||||
}
|
||||
|
||||
int nv_kthread_q_init_on_node(nv_kthread_q_t *q, const char *q_name, int preferred_node)
|
||||
{
|
||||
memset(q, 0, sizeof(*q));
|
||||
|
||||
INIT_LIST_HEAD(&q->q_list_head);
|
||||
spin_lock_init(&q->q_lock);
|
||||
sema_init(&q->q_sem, 0);
|
||||
|
||||
if (preferred_node == NV_KTHREAD_NO_NODE) {
|
||||
q->q_kthread = kthread_create(_main_loop, q, q_name);
|
||||
}
|
||||
else {
|
||||
q->q_kthread = thread_create_on_node(_main_loop, q, preferred_node, q_name);
|
||||
}
|
||||
|
||||
if (IS_ERR(q->q_kthread)) {
|
||||
int err = PTR_ERR(q->q_kthread);
|
||||
|
||||
// Clear q_kthread before returning so that nv_kthread_q_stop() can be
|
||||
// safely called on it making error handling easier.
|
||||
q->q_kthread = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
wake_up_process(q->q_kthread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns true (non-zero) if the item was actually scheduled, and false if the
|
||||
// item was already pending in a queue.
|
||||
static int _raw_q_schedule(nv_kthread_q_t *q, nv_kthread_q_item_t *q_item)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 1;
|
||||
|
||||
spin_lock_irqsave(&q->q_lock, flags);
|
||||
|
||||
if (likely(list_empty(&q_item->q_list_node)))
|
||||
list_add_tail(&q_item->q_list_node, &q->q_list_head);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
spin_unlock_irqrestore(&q->q_lock, flags);
|
||||
|
||||
if (likely(ret))
|
||||
up(&q->q_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void nv_kthread_q_item_init(nv_kthread_q_item_t *q_item,
|
||||
nv_q_func_t function_to_run,
|
||||
void *function_args)
|
||||
{
|
||||
INIT_LIST_HEAD(&q_item->q_list_node);
|
||||
q_item->function_to_run = function_to_run;
|
||||
q_item->function_args = function_args;
|
||||
}
|
||||
|
||||
// Returns true (non-zero) if the q_item got scheduled, false otherwise.
|
||||
int nv_kthread_q_schedule_q_item(nv_kthread_q_t *q,
|
||||
nv_kthread_q_item_t *q_item)
|
||||
{
|
||||
if (unlikely(atomic_read(&q->main_loop_should_exit))) {
|
||||
NVQ_WARN("Not allowed: nv_kthread_q_schedule_q_item was "
|
||||
"called with a non-alive q: 0x%p\n", q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _raw_q_schedule(q, q_item);
|
||||
}
|
||||
|
||||
static void _q_flush_function(void *args)
|
||||
{
|
||||
struct completion *completion = (struct completion *)args;
|
||||
complete(completion);
|
||||
}
|
||||
|
||||
|
||||
static void _raw_q_flush(nv_kthread_q_t *q)
|
||||
{
|
||||
nv_kthread_q_item_t q_item;
|
||||
DECLARE_COMPLETION_ONSTACK(completion);
|
||||
|
||||
nv_kthread_q_item_init(&q_item, _q_flush_function, &completion);
|
||||
|
||||
_raw_q_schedule(q, &q_item);
|
||||
|
||||
// Wait for the flush item to run. Once it has run, then all of the
|
||||
// previously queued items in front of it will have run, so that means
|
||||
// the flush is complete.
|
||||
wait_for_completion(&completion);
|
||||
}
|
||||
|
||||
void nv_kthread_q_flush(nv_kthread_q_t *q)
|
||||
{
|
||||
if (unlikely(atomic_read(&q->main_loop_should_exit))) {
|
||||
NVQ_WARN("Not allowed: nv_kthread_q_flush was called after "
|
||||
"nv_kthread_q_stop. q: 0x%p\n", q);
|
||||
return;
|
||||
}
|
||||
|
||||
// This 2x flush is not a typing mistake. The queue really does have to be
|
||||
// flushed twice, in order to take care of the case of a q_item that
|
||||
// reschedules itself.
|
||||
_raw_q_flush(q);
|
||||
_raw_q_flush(q);
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nv-memdbg.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
/* track who's allocating memory and print out a list of leaked allocations at
|
||||
* teardown.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
struct rb_node rb_node;
|
||||
void *addr;
|
||||
NvU64 size;
|
||||
NvU32 line;
|
||||
const char *file;
|
||||
} nv_memdbg_node_t;
|
||||
|
||||
struct
|
||||
{
|
||||
struct rb_root rb_root;
|
||||
NvU64 untracked_bytes;
|
||||
NvU64 num_untracked_allocs;
|
||||
nv_spinlock_t lock;
|
||||
} g_nv_memdbg;
|
||||
|
||||
void nv_memdbg_init(void)
|
||||
{
|
||||
NV_SPIN_LOCK_INIT(&g_nv_memdbg.lock);
|
||||
g_nv_memdbg.rb_root = RB_ROOT;
|
||||
}
|
||||
|
||||
static nv_memdbg_node_t *nv_memdbg_node_entry(struct rb_node *rb_node)
|
||||
{
|
||||
return rb_entry(rb_node, nv_memdbg_node_t, rb_node);
|
||||
}
|
||||
|
||||
static void nv_memdbg_insert_node(nv_memdbg_node_t *new)
|
||||
{
|
||||
nv_memdbg_node_t *node;
|
||||
struct rb_node **rb_node = &g_nv_memdbg.rb_root.rb_node;
|
||||
struct rb_node *rb_parent = NULL;
|
||||
|
||||
while (*rb_node)
|
||||
{
|
||||
node = nv_memdbg_node_entry(*rb_node);
|
||||
|
||||
WARN_ON(new->addr == node->addr);
|
||||
|
||||
rb_parent = *rb_node;
|
||||
|
||||
if (new->addr < node->addr)
|
||||
rb_node = &(*rb_node)->rb_left;
|
||||
else
|
||||
rb_node = &(*rb_node)->rb_right;
|
||||
}
|
||||
|
||||
rb_link_node(&new->rb_node, rb_parent, rb_node);
|
||||
rb_insert_color(&new->rb_node, &g_nv_memdbg.rb_root);
|
||||
}
|
||||
|
||||
static nv_memdbg_node_t *nv_memdbg_remove_node(void *addr)
|
||||
{
|
||||
nv_memdbg_node_t *node = NULL;
|
||||
struct rb_node *rb_node = g_nv_memdbg.rb_root.rb_node;
|
||||
|
||||
while (rb_node)
|
||||
{
|
||||
node = nv_memdbg_node_entry(rb_node);
|
||||
if (addr == node->addr)
|
||||
break;
|
||||
else if (addr < node->addr)
|
||||
rb_node = rb_node->rb_left;
|
||||
else
|
||||
rb_node = rb_node->rb_right;
|
||||
}
|
||||
|
||||
WARN_ON(!node || node->addr != addr);
|
||||
|
||||
rb_erase(&node->rb_node, &g_nv_memdbg.rb_root);
|
||||
return node;
|
||||
}
|
||||
|
||||
void nv_memdbg_add(void *addr, NvU64 size, const char *file, int line)
|
||||
{
|
||||
nv_memdbg_node_t *node;
|
||||
unsigned long flags;
|
||||
|
||||
WARN_ON(addr == NULL);
|
||||
|
||||
/* If node allocation fails, we can still update the untracked counters */
|
||||
node = kmalloc(sizeof(*node),
|
||||
NV_MAY_SLEEP() ? NV_GFP_KERNEL : NV_GFP_ATOMIC);
|
||||
if (node)
|
||||
{
|
||||
node->addr = addr;
|
||||
node->size = size;
|
||||
node->file = file;
|
||||
node->line = line;
|
||||
}
|
||||
|
||||
NV_SPIN_LOCK_IRQSAVE(&g_nv_memdbg.lock, flags);
|
||||
|
||||
if (node)
|
||||
{
|
||||
nv_memdbg_insert_node(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
++g_nv_memdbg.num_untracked_allocs;
|
||||
g_nv_memdbg.untracked_bytes += size;
|
||||
}
|
||||
|
||||
NV_SPIN_UNLOCK_IRQRESTORE(&g_nv_memdbg.lock, flags);
|
||||
}
|
||||
|
||||
void nv_memdbg_remove(void *addr, NvU64 size, const char *file, int line)
|
||||
{
|
||||
nv_memdbg_node_t *node;
|
||||
unsigned long flags;
|
||||
|
||||
NV_SPIN_LOCK_IRQSAVE(&g_nv_memdbg.lock, flags);
|
||||
|
||||
node = nv_memdbg_remove_node(addr);
|
||||
if (!node)
|
||||
{
|
||||
WARN_ON(g_nv_memdbg.num_untracked_allocs == 0);
|
||||
WARN_ON(g_nv_memdbg.untracked_bytes < size);
|
||||
--g_nv_memdbg.num_untracked_allocs;
|
||||
g_nv_memdbg.untracked_bytes -= size;
|
||||
}
|
||||
|
||||
NV_SPIN_UNLOCK_IRQRESTORE(&g_nv_memdbg.lock, flags);
|
||||
|
||||
if (node)
|
||||
{
|
||||
if ((size != 0) && (node->size != size))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: size mismatch on free: %llu != %llu\n",
|
||||
size, node->size);
|
||||
if (node->file)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: allocation: 0x%p @ %s:%d\n",
|
||||
node->addr, node->file, node->line);
|
||||
}
|
||||
else
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: allocation: 0x%p\n",
|
||||
node->addr);
|
||||
}
|
||||
os_dbg_breakpoint();
|
||||
}
|
||||
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
void nv_memdbg_exit(void)
|
||||
{
|
||||
nv_memdbg_node_t *node;
|
||||
NvU64 leaked_bytes = 0, num_leaked_allocs = 0;
|
||||
|
||||
if (!RB_EMPTY_ROOT(&g_nv_memdbg.rb_root))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: list of leaked memory allocations:\n");
|
||||
}
|
||||
|
||||
while (!RB_EMPTY_ROOT(&g_nv_memdbg.rb_root))
|
||||
{
|
||||
node = nv_memdbg_node_entry(rb_first(&g_nv_memdbg.rb_root));
|
||||
|
||||
leaked_bytes += node->size;
|
||||
++num_leaked_allocs;
|
||||
|
||||
if (node->file)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %llu bytes, 0x%p @ %s:%d\n",
|
||||
node->size, node->addr, node->file, node->line);
|
||||
}
|
||||
else
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %llu bytes, 0x%p\n",
|
||||
node->size, node->addr);
|
||||
}
|
||||
|
||||
rb_erase(&node->rb_node, &g_nv_memdbg.rb_root);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
/* If we failed to allocate a node at some point, we may have leaked memory
|
||||
* even if the tree is empty */
|
||||
if (num_leaked_allocs > 0 || g_nv_memdbg.num_untracked_allocs > 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: total leaked memory: %llu bytes in %llu allocations\n",
|
||||
leaked_bytes + g_nv_memdbg.untracked_bytes,
|
||||
num_leaked_allocs + g_nv_memdbg.num_untracked_allocs);
|
||||
|
||||
if (g_nv_memdbg.num_untracked_allocs > 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %llu bytes in %llu allocations untracked\n",
|
||||
g_nv_memdbg.untracked_bytes, g_nv_memdbg.num_untracked_allocs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,802 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv_speculation_barrier.h"
|
||||
|
||||
/*
|
||||
* The 'struct vm_operations' open() callback is called by the Linux
|
||||
* kernel when the parent VMA is split or copied, close() when the
|
||||
* current VMA is about to be deleted.
|
||||
*
|
||||
* We implement these callbacks to keep track of the number of user
|
||||
* mappings of system memory allocations. This was motivated by a
|
||||
* subtle interaction problem between the driver and the kernel with
|
||||
* respect to the bookkeeping of pages marked reserved and later
|
||||
* mapped with mmap().
|
||||
*
|
||||
* Traditionally, the Linux kernel ignored reserved pages, such that
|
||||
* when they were mapped via mmap(), the integrity of their usage
|
||||
* counts depended on the reserved bit being set for as long as user
|
||||
* mappings existed.
|
||||
*
|
||||
* Since we mark system memory pages allocated for DMA reserved and
|
||||
* typically map them with mmap(), we need to ensure they remain
|
||||
* reserved until the last mapping has been torn down. This worked
|
||||
* correctly in most cases, but in a few, the RM API called into the
|
||||
* RM to free memory before calling munmap() to unmap it.
|
||||
*
|
||||
* In the past, we allowed nv_free_pages() to remove the 'at' from
|
||||
* the parent device's allocation list in this case, but didn't
|
||||
* release the underlying pages until the last user mapping had been
|
||||
* destroyed:
|
||||
*
|
||||
* In nvidia_vma_release(), we freed any resources associated with
|
||||
* the allocation (IOMMU mappings, etc.) and cleared the
|
||||
* underlying pages' reserved bits, but didn't free them. The kernel
|
||||
* was expected to do this.
|
||||
*
|
||||
* This worked in practise, but made dangerous assumptions about the
|
||||
* kernel's behavior and could fail in some cases. We now handle
|
||||
* this case differently (see below).
|
||||
*/
|
||||
static void
|
||||
nvidia_vma_open(struct vm_area_struct *vma)
|
||||
{
|
||||
nv_alloc_t *at = NV_VMA_PRIVATE(vma);
|
||||
|
||||
NV_PRINT_VMA(NV_DBG_MEMINFO, vma);
|
||||
|
||||
if (at != NULL)
|
||||
{
|
||||
NV_ATOMIC_INC(at->usage_count);
|
||||
|
||||
NV_PRINT_AT(NV_DBG_MEMINFO, at);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (see above for additional information)
|
||||
*
|
||||
* If the 'at' usage count drops to zero with the updated logic, the
|
||||
* the allocation is recorded in the free list of the private
|
||||
* data associated with the file pointer; nvidia_close() uses this
|
||||
* list to perform deferred free operations when the parent file
|
||||
* descriptor is closed. This will typically happen when the process
|
||||
* exits.
|
||||
*
|
||||
* Since this is technically a workaround to handle possible fallout
|
||||
* from misbehaving clients, we additionally print a warning.
|
||||
*/
|
||||
static void
|
||||
nvidia_vma_release(struct vm_area_struct *vma)
|
||||
{
|
||||
nv_alloc_t *at = NV_VMA_PRIVATE(vma);
|
||||
nv_linux_file_private_t *nvlfp = NV_GET_LINUX_FILE_PRIVATE(NV_VMA_FILE(vma));
|
||||
static int count = 0;
|
||||
|
||||
NV_PRINT_VMA(NV_DBG_MEMINFO, vma);
|
||||
|
||||
if (at != NULL && nv_alloc_release(nvlfp, at))
|
||||
{
|
||||
if ((at->pid == os_get_current_process()) &&
|
||||
(count++ < NV_MAX_RECURRING_WARNING_MESSAGES))
|
||||
{
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: late unmap, comm: %s, 0x%p\n",
|
||||
__FUNCTION__, current->comm, at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nvidia_vma_access(
|
||||
struct vm_area_struct *vma,
|
||||
unsigned long addr,
|
||||
void *buffer,
|
||||
int length,
|
||||
int write
|
||||
)
|
||||
{
|
||||
nv_alloc_t *at = NULL;
|
||||
nv_linux_file_private_t *nvlfp = NV_GET_LINUX_FILE_PRIVATE(NV_VMA_FILE(vma));
|
||||
nv_state_t *nv = NV_STATE_PTR(nvlfp->nvptr);
|
||||
NvU32 pageIndex, pageOffset;
|
||||
void *kernel_mapping;
|
||||
const nv_alloc_mapping_context_t *mmap_context = &nvlfp->mmap_context;
|
||||
NvU64 offset;
|
||||
|
||||
pageIndex = ((addr - vma->vm_start) >> PAGE_SHIFT);
|
||||
pageOffset = (addr & ~PAGE_MASK);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!mmap_context->valid)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "NVRM: VM: invalid mmap context\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offset = mmap_context->mmap_start;
|
||||
|
||||
if (nv->flags & NV_FLAG_CONTROL)
|
||||
{
|
||||
at = NV_VMA_PRIVATE(vma);
|
||||
|
||||
/*
|
||||
* at can be NULL for peer IO mem.
|
||||
*/
|
||||
if (!at)
|
||||
return -EINVAL;
|
||||
|
||||
if (pageIndex >= at->num_pages)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* For PPC64LE build, nv_array_index_no_speculate() is not defined
|
||||
* therefore call nv_speculation_barrier().
|
||||
* When this definition is added, this platform check should be removed.
|
||||
*/
|
||||
#if !defined(NVCPU_PPC64LE)
|
||||
pageIndex = nv_array_index_no_speculate(pageIndex, at->num_pages);
|
||||
#else
|
||||
nv_speculation_barrier();
|
||||
#endif
|
||||
kernel_mapping = (void *)(at->page_table[pageIndex]->virt_addr + pageOffset);
|
||||
}
|
||||
else if (IS_FB_OFFSET(nv, offset, length))
|
||||
{
|
||||
addr = (offset & PAGE_MASK);
|
||||
kernel_mapping = os_map_kernel_space(addr, PAGE_SIZE, NV_MEMORY_UNCACHED);
|
||||
if (kernel_mapping == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
kernel_mapping = ((char *)kernel_mapping + pageOffset);
|
||||
}
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
length = NV_MIN(length, (int)(PAGE_SIZE - pageOffset));
|
||||
|
||||
if (write)
|
||||
memcpy(kernel_mapping, buffer, length);
|
||||
else
|
||||
memcpy(buffer, kernel_mapping, length);
|
||||
|
||||
if (at == NULL)
|
||||
{
|
||||
kernel_mapping = ((char *)kernel_mapping - pageOffset);
|
||||
os_unmap_kernel_space(kernel_mapping, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static vm_fault_t nvidia_fault(
|
||||
#if !defined(NV_VM_OPS_FAULT_REMOVED_VMA_ARG)
|
||||
struct vm_area_struct *vma,
|
||||
#endif
|
||||
struct vm_fault *vmf
|
||||
)
|
||||
{
|
||||
#if defined(NV_VM_OPS_FAULT_REMOVED_VMA_ARG)
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
#endif
|
||||
nv_linux_file_private_t *nvlfp = NV_GET_LINUX_FILE_PRIVATE(NV_VMA_FILE(vma));
|
||||
nv_linux_state_t *nvl = nvlfp->nvptr;
|
||||
nv_state_t *nv = NV_STATE_PTR(nvl);
|
||||
vm_fault_t ret = VM_FAULT_NOPAGE;
|
||||
|
||||
NvU64 page;
|
||||
NvU64 num_pages = NV_VMA_SIZE(vma) >> PAGE_SHIFT;
|
||||
NvU64 pfn_start = (nvlfp->mmap_context.mmap_start >> PAGE_SHIFT);
|
||||
|
||||
if (vma->vm_pgoff != 0)
|
||||
{
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
// Mapping revocation is only supported for GPU mappings.
|
||||
if (NV_IS_CTL_DEVICE(nv))
|
||||
{
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
// Wake up GPU and reinstate mappings only if we are not in S3/S4 entry
|
||||
if (!down_read_trylock(&nv_system_pm_lock))
|
||||
{
|
||||
return VM_FAULT_NOPAGE;
|
||||
}
|
||||
|
||||
down(&nvl->mmap_lock);
|
||||
|
||||
// Wake up the GPU if it is not currently safe to mmap.
|
||||
if (!nvl->safe_to_mmap)
|
||||
{
|
||||
NV_STATUS status;
|
||||
|
||||
if (!nvl->gpu_wakeup_callback_needed)
|
||||
{
|
||||
// GPU wakeup callback already scheduled.
|
||||
up(&nvl->mmap_lock);
|
||||
up_read(&nv_system_pm_lock);
|
||||
return VM_FAULT_NOPAGE;
|
||||
}
|
||||
|
||||
/*
|
||||
* GPU wakeup cannot be completed directly in the fault handler due to the
|
||||
* inability to take the GPU lock while mmap_lock is held.
|
||||
*/
|
||||
status = rm_schedule_gpu_wakeup(nvl->sp[NV_DEV_STACK_GPU_WAKEUP], nv);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: rm_schedule_gpu_wakeup failed: %x\n", status);
|
||||
up(&nvl->mmap_lock);
|
||||
up_read(&nv_system_pm_lock);
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
// Ensure that we do not schedule duplicate GPU wakeup callbacks.
|
||||
nvl->gpu_wakeup_callback_needed = NV_FALSE;
|
||||
|
||||
up(&nvl->mmap_lock);
|
||||
up_read(&nv_system_pm_lock);
|
||||
return VM_FAULT_NOPAGE;
|
||||
}
|
||||
|
||||
// Safe to mmap, map all pages in this VMA.
|
||||
for (page = 0; page < num_pages; page++)
|
||||
{
|
||||
NvU64 virt_addr = vma->vm_start + (page << PAGE_SHIFT);
|
||||
NvU64 pfn = pfn_start + page;
|
||||
|
||||
ret = nv_insert_pfn(vma, virt_addr, pfn,
|
||||
nvlfp->mmap_context.remap_prot_extra);
|
||||
if (ret != VM_FAULT_NOPAGE)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: nv_insert_pfn failed: %x\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
nvl->all_mappings_revoked = NV_FALSE;
|
||||
}
|
||||
up(&nvl->mmap_lock);
|
||||
up_read(&nv_system_pm_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct nv_vm_ops = {
|
||||
.open = nvidia_vma_open,
|
||||
.close = nvidia_vma_release,
|
||||
.fault = nvidia_fault,
|
||||
.access = nvidia_vma_access,
|
||||
};
|
||||
|
||||
int nv_encode_caching(
|
||||
pgprot_t *prot,
|
||||
NvU32 cache_type,
|
||||
nv_memory_type_t memory_type
|
||||
)
|
||||
{
|
||||
pgprot_t tmp;
|
||||
|
||||
if (prot == NULL)
|
||||
{
|
||||
tmp = __pgprot(0);
|
||||
prot = &tmp;
|
||||
}
|
||||
|
||||
switch (cache_type)
|
||||
{
|
||||
case NV_MEMORY_UNCACHED_WEAK:
|
||||
#if defined(NV_PGPROT_UNCACHED_WEAK)
|
||||
*prot = NV_PGPROT_UNCACHED_WEAK(*prot);
|
||||
break;
|
||||
#endif
|
||||
case NV_MEMORY_UNCACHED:
|
||||
*prot = (memory_type == NV_MEMORY_TYPE_SYSTEM) ?
|
||||
NV_PGPROT_UNCACHED(*prot) :
|
||||
NV_PGPROT_UNCACHED_DEVICE(*prot);
|
||||
break;
|
||||
#if defined(NV_PGPROT_WRITE_COMBINED) && \
|
||||
defined(NV_PGPROT_WRITE_COMBINED_DEVICE)
|
||||
case NV_MEMORY_DEFAULT:
|
||||
case NV_MEMORY_WRITECOMBINED:
|
||||
if (NV_ALLOW_WRITE_COMBINING(memory_type))
|
||||
{
|
||||
*prot = (memory_type == NV_MEMORY_TYPE_FRAMEBUFFER) ?
|
||||
NV_PGPROT_WRITE_COMBINED_DEVICE(*prot) :
|
||||
NV_PGPROT_WRITE_COMBINED(*prot);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If WC support is unavailable, we need to return an error
|
||||
* code to the caller, but need not print a warning.
|
||||
*
|
||||
* For frame buffer memory, callers are expected to use the
|
||||
* UC- memory type if we report WC as unsupported, which
|
||||
* translates to the effective memory type WC if a WC MTRR
|
||||
* exists or else UC.
|
||||
*/
|
||||
return 1;
|
||||
#endif
|
||||
case NV_MEMORY_CACHED:
|
||||
if (!NV_ALLOW_CACHING(memory_type))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: memory type %d does not allow caching!\n",
|
||||
memory_type);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: cache type %d not supported for memory type %d!\n",
|
||||
cache_type, memory_type);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int static nvidia_mmap_peer_io(
|
||||
struct vm_area_struct *vma,
|
||||
nv_alloc_t *at,
|
||||
NvU64 page_index,
|
||||
NvU64 pages
|
||||
)
|
||||
{
|
||||
int ret;
|
||||
NvU64 start;
|
||||
NvU64 size;
|
||||
|
||||
BUG_ON(!at->flags.contig);
|
||||
|
||||
start = at->page_table[page_index]->phys_addr;
|
||||
size = pages * PAGE_SIZE;
|
||||
|
||||
ret = nv_io_remap_page_range(vma, start, size, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int static nvidia_mmap_sysmem(
|
||||
struct vm_area_struct *vma,
|
||||
nv_alloc_t *at,
|
||||
NvU64 page_index,
|
||||
NvU64 pages
|
||||
)
|
||||
{
|
||||
NvU64 j;
|
||||
int ret = 0;
|
||||
unsigned long start = 0;
|
||||
|
||||
NV_ATOMIC_INC(at->usage_count);
|
||||
|
||||
start = vma->vm_start;
|
||||
for (j = page_index; j < (page_index + pages); j++)
|
||||
{
|
||||
/*
|
||||
* For PPC64LE build, nv_array_index_no_speculate() is not defined
|
||||
* therefore call nv_speculation_barrier().
|
||||
* When this definition is added, this platform check should be removed.
|
||||
*/
|
||||
#if !defined(NVCPU_PPC64LE)
|
||||
j = nv_array_index_no_speculate(j, (page_index + pages));
|
||||
#else
|
||||
nv_speculation_barrier();
|
||||
#endif
|
||||
|
||||
#if defined(NV_VGPU_KVM_BUILD)
|
||||
if (at->flags.guest)
|
||||
{
|
||||
ret = nv_remap_page_range(vma, start, at->page_table[j]->phys_addr,
|
||||
PAGE_SIZE, vma->vm_page_prot);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
vma->vm_page_prot = nv_adjust_pgprot(vma->vm_page_prot, 0);
|
||||
ret = vm_insert_page(vma, start,
|
||||
NV_GET_PAGE_STRUCT(at->page_table[j]->phys_addr));
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
NV_ATOMIC_DEC(at->usage_count);
|
||||
return -EAGAIN;
|
||||
}
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nvidia_mmap_numa(
|
||||
struct vm_area_struct *vma,
|
||||
const nv_alloc_mapping_context_t *mmap_context)
|
||||
{
|
||||
NvU64 start, addr;
|
||||
NvU64 pages;
|
||||
NvU64 i;
|
||||
|
||||
pages = NV_VMA_SIZE(vma) >> PAGE_SHIFT;
|
||||
start = vma->vm_start;
|
||||
|
||||
if (mmap_context->num_pages < pages)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Needed for the linux kernel for mapping compound pages
|
||||
nv_vm_flags_set(vma, VM_MIXEDMAP);
|
||||
|
||||
for (i = 0, addr = mmap_context->page_array[0]; i < pages;
|
||||
addr = mmap_context->page_array[++i], start += PAGE_SIZE)
|
||||
{
|
||||
if (vm_insert_page(vma, start, NV_GET_PAGE_STRUCT(addr)) != 0)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nvidia_mmap_helper(
|
||||
nv_state_t *nv,
|
||||
nv_linux_file_private_t *nvlfp,
|
||||
nvidia_stack_t *sp,
|
||||
struct vm_area_struct *vma,
|
||||
void *vm_priv
|
||||
)
|
||||
{
|
||||
NvU32 prot = 0;
|
||||
int ret;
|
||||
const nv_alloc_mapping_context_t *mmap_context = &nvlfp->mmap_context;
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
NV_STATUS status;
|
||||
|
||||
if (nvlfp == NULL)
|
||||
return NV_ERR_INVALID_ARGUMENT;
|
||||
|
||||
/*
|
||||
* If mmap context is not valid on this file descriptor, this mapping wasn't
|
||||
* previously validated with the RM so it must be rejected.
|
||||
*/
|
||||
if (!mmap_context->valid)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "NVRM: VM: invalid mmap\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (vma->vm_pgoff != 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
NV_PRINT_VMA(NV_DBG_MEMINFO, vma);
|
||||
|
||||
status = nv_check_gpu_state(nv);
|
||||
if (status != NV_OK)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_INFO, nv,
|
||||
"GPU is lost, skipping nvidia_mmap_helper\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
NV_VMA_PRIVATE(vma) = vm_priv;
|
||||
|
||||
prot = mmap_context->prot;
|
||||
|
||||
/*
|
||||
* Nvidia device node(nvidia#) maps device's BAR memory,
|
||||
* Nvidia control node(nvidiactrl) maps system memory.
|
||||
*/
|
||||
if (!NV_IS_CTL_DEVICE(nv))
|
||||
{
|
||||
NvU32 remap_prot_extra = mmap_context->remap_prot_extra;
|
||||
NvU64 mmap_start = mmap_context->mmap_start;
|
||||
NvU64 mmap_length = mmap_context->mmap_size;
|
||||
NvU64 access_start = mmap_context->access_start;
|
||||
NvU64 access_len = mmap_context->access_size;
|
||||
|
||||
// validate the size
|
||||
if (NV_VMA_SIZE(vma) != mmap_length)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (IS_REG_OFFSET(nv, access_start, access_len))
|
||||
{
|
||||
if (nv_encode_caching(&vma->vm_page_prot, NV_MEMORY_UNCACHED,
|
||||
NV_MEMORY_TYPE_REGISTERS))
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
else if (IS_FB_OFFSET(nv, access_start, access_len))
|
||||
{
|
||||
if (IS_UD_OFFSET(nv, access_start, access_len))
|
||||
{
|
||||
if (nv_encode_caching(&vma->vm_page_prot, NV_MEMORY_UNCACHED,
|
||||
NV_MEMORY_TYPE_FRAMEBUFFER))
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nv_encode_caching(&vma->vm_page_prot,
|
||||
rm_disable_iomap_wc() ? NV_MEMORY_UNCACHED : mmap_context->caching,
|
||||
NV_MEMORY_TYPE_FRAMEBUFFER))
|
||||
{
|
||||
if (nv_encode_caching(&vma->vm_page_prot,
|
||||
NV_MEMORY_UNCACHED_WEAK, NV_MEMORY_TYPE_FRAMEBUFFER))
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
down(&nvl->mmap_lock);
|
||||
if (nvl->safe_to_mmap)
|
||||
{
|
||||
nvl->all_mappings_revoked = NV_FALSE;
|
||||
|
||||
//
|
||||
// This path is similar to the sysmem mapping code.
|
||||
// TODO: Refactor is needed as part of bug#2001704.
|
||||
//
|
||||
if ((nv_get_numa_status(nvl) == NV_NUMA_STATUS_ONLINE) &&
|
||||
!IS_REG_OFFSET(nv, access_start, access_len))
|
||||
{
|
||||
ret = nvidia_mmap_numa(vma, mmap_context);
|
||||
if (ret)
|
||||
{
|
||||
up(&nvl->mmap_lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nv_io_remap_page_range(vma, mmap_start, mmap_length,
|
||||
remap_prot_extra) != 0)
|
||||
{
|
||||
up(&nvl->mmap_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
up(&nvl->mmap_lock);
|
||||
|
||||
nv_vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
nv_alloc_t *at;
|
||||
NvU64 page_index;
|
||||
NvU64 pages;
|
||||
NvU64 mmap_size;
|
||||
|
||||
at = (nv_alloc_t *)mmap_context->alloc;
|
||||
page_index = mmap_context->page_index;
|
||||
mmap_size = NV_VMA_SIZE(vma);
|
||||
pages = mmap_size >> PAGE_SHIFT;
|
||||
|
||||
if ((page_index + pages) > at->num_pages)
|
||||
{
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callers that pass in non-NULL VMA private data must never reach this
|
||||
* code. They should be mapping on a non-control node.
|
||||
*/
|
||||
BUG_ON(NV_VMA_PRIVATE(vma));
|
||||
|
||||
if (at->flags.peer_io)
|
||||
{
|
||||
if (nv_encode_caching(&vma->vm_page_prot,
|
||||
at->cache_type,
|
||||
NV_MEMORY_TYPE_DEVICE_MMIO))
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* There is no need to keep 'peer IO at' alive till vma_release like
|
||||
* 'sysmem at' because there are no security concerns where a client
|
||||
* could free RM allocated sysmem before unmapping it. Hence, vm_ops
|
||||
* are NOP, and at->usage_count is never being used.
|
||||
*/
|
||||
NV_VMA_PRIVATE(vma) = NULL;
|
||||
|
||||
ret = nvidia_mmap_peer_io(vma, at, page_index, pages);
|
||||
|
||||
BUG_ON(NV_VMA_PRIVATE(vma));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nv_encode_caching(&vma->vm_page_prot,
|
||||
at->cache_type,
|
||||
NV_MEMORY_TYPE_SYSTEM))
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
NV_VMA_PRIVATE(vma) = at;
|
||||
|
||||
ret = nvidia_mmap_sysmem(vma, at, page_index, pages);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
NV_PRINT_AT(NV_DBG_MEMINFO, at);
|
||||
|
||||
nv_vm_flags_set(vma, VM_IO | VM_LOCKED | VM_RESERVED);
|
||||
nv_vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
|
||||
}
|
||||
|
||||
if ((prot & NV_PROTECT_WRITEABLE) == 0)
|
||||
{
|
||||
vma->vm_page_prot = NV_PGPROT_READ_ONLY(vma->vm_page_prot);
|
||||
nv_vm_flags_clear(vma, VM_WRITE);
|
||||
nv_vm_flags_clear(vma, VM_MAYWRITE);
|
||||
}
|
||||
|
||||
vma->vm_ops = &nv_vm_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nvidia_mmap(
|
||||
struct file *file,
|
||||
struct vm_area_struct *vma
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_FILEP(file);
|
||||
nv_state_t *nv = NV_STATE_PTR(nvl);
|
||||
nv_linux_file_private_t *nvlfp = NV_GET_LINUX_FILE_PRIVATE(file);
|
||||
nvidia_stack_t *sp = NULL;
|
||||
int status;
|
||||
|
||||
//
|
||||
// Do not allow mmap operation if this is a fd into
|
||||
// which rm objects have been exported.
|
||||
//
|
||||
if (nvlfp->nvfp.handles != NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sp = nv_nvlfp_get_sp(nvlfp, NV_FOPS_STACK_INDEX_MMAP);
|
||||
|
||||
status = nvidia_mmap_helper(nv, nvlfp, sp, vma, NULL);
|
||||
|
||||
nv_nvlfp_put_sp(nvlfp, NV_FOPS_STACK_INDEX_MMAP);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
nv_revoke_gpu_mappings_locked(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
nv_linux_file_private_t *nvlfp;
|
||||
|
||||
/* Revoke all mappings for every open file */
|
||||
list_for_each_entry (nvlfp, &nvl->open_files, entry)
|
||||
{
|
||||
unmap_mapping_range(&nvlfp->mapping, 0, ~0, 1);
|
||||
}
|
||||
|
||||
nvl->all_mappings_revoked = NV_TRUE;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_revoke_gpu_mappings(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
// Mapping revocation is only supported for GPU mappings.
|
||||
if (NV_IS_CTL_DEVICE(nv))
|
||||
{
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
down(&nvl->mmap_lock);
|
||||
|
||||
nv_revoke_gpu_mappings_locked(nv);
|
||||
|
||||
up(&nvl->mmap_lock);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_acquire_mmap_lock(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
down(&nvl->mmap_lock);
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_release_mmap_lock(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
up(&nvl->mmap_lock);
|
||||
}
|
||||
|
||||
NvBool NV_API_CALL nv_get_all_mappings_revoked_locked(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
// Caller must hold nvl->mmap_lock for all decisions based on this
|
||||
return nvl->all_mappings_revoked;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_set_safe_to_mmap_locked(
|
||||
nv_state_t *nv,
|
||||
NvBool safe_to_mmap
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
// Caller must hold nvl->mmap_lock
|
||||
|
||||
/*
|
||||
* If nvl->safe_to_mmap is transitioning from TRUE to FALSE, we expect to
|
||||
* need to schedule a GPU wakeup callback when we fault.
|
||||
*
|
||||
* nvl->gpu_wakeup_callback_needed will be set to FALSE in nvidia_fault()
|
||||
* after scheduling the GPU wakeup callback, preventing us from scheduling
|
||||
* duplicates.
|
||||
*/
|
||||
if (!safe_to_mmap && nvl->safe_to_mmap)
|
||||
{
|
||||
nvl->gpu_wakeup_callback_needed = NV_TRUE;
|
||||
}
|
||||
|
||||
nvl->safe_to_mmap = safe_to_mmap;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nv-modeset-interface.h"
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nvstatus.h"
|
||||
#include "nv.h"
|
||||
|
||||
static const nvidia_modeset_callbacks_t *nv_modeset_callbacks;
|
||||
|
||||
static int nvidia_modeset_rm_ops_alloc_stack(nvidia_stack_t **sp)
|
||||
{
|
||||
return nv_kmem_cache_alloc_stack(sp);
|
||||
}
|
||||
|
||||
static void nvidia_modeset_rm_ops_free_stack(nvidia_stack_t *sp)
|
||||
{
|
||||
if (sp != NULL)
|
||||
{
|
||||
nv_kmem_cache_free_stack(sp);
|
||||
}
|
||||
}
|
||||
|
||||
static int nvidia_modeset_set_callbacks(const nvidia_modeset_callbacks_t *cb)
|
||||
{
|
||||
if ((nv_modeset_callbacks != NULL && cb != NULL) ||
|
||||
(nv_modeset_callbacks == NULL && cb == NULL))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nv_modeset_callbacks = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nvidia_modeset_suspend(NvU32 gpuId)
|
||||
{
|
||||
if (nv_modeset_callbacks)
|
||||
{
|
||||
nv_modeset_callbacks->suspend(gpuId);
|
||||
}
|
||||
}
|
||||
|
||||
void nvidia_modeset_resume(NvU32 gpuId)
|
||||
{
|
||||
if (nv_modeset_callbacks)
|
||||
{
|
||||
nv_modeset_callbacks->resume(gpuId);
|
||||
}
|
||||
}
|
||||
|
||||
static NvU32 nvidia_modeset_enumerate_gpus(nv_gpu_info_t *gpu_info)
|
||||
{
|
||||
nv_linux_state_t *nvl;
|
||||
unsigned int count;
|
||||
|
||||
LOCK_NV_LINUX_DEVICES();
|
||||
|
||||
count = 0;
|
||||
|
||||
for (nvl = nv_linux_devices; nvl != NULL; nvl = nvl->next)
|
||||
{
|
||||
nv_state_t *nv = NV_STATE_PTR(nvl);
|
||||
|
||||
/*
|
||||
* The gpu_info[] array has NV_MAX_GPUS elements. Fail if there
|
||||
* are more GPUs than that.
|
||||
*/
|
||||
if (count >= NV_MAX_GPUS) {
|
||||
nv_printf(NV_DBG_WARNINGS, "NVRM: More than %d GPUs found.",
|
||||
NV_MAX_GPUS);
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
gpu_info[count].gpu_id = nv->gpu_id;
|
||||
|
||||
gpu_info[count].pci_info.domain = nv->pci_info.domain;
|
||||
gpu_info[count].pci_info.bus = nv->pci_info.bus;
|
||||
gpu_info[count].pci_info.slot = nv->pci_info.slot;
|
||||
gpu_info[count].pci_info.function = nv->pci_info.function;
|
||||
|
||||
gpu_info[count].os_device_ptr = nvl->dev;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
UNLOCK_NV_LINUX_DEVICES();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
NV_STATUS nvidia_get_rm_ops(nvidia_modeset_rm_ops_t *rm_ops)
|
||||
{
|
||||
const nvidia_modeset_rm_ops_t local_rm_ops = {
|
||||
.version_string = NV_VERSION_STRING,
|
||||
.system_info = {
|
||||
.allow_write_combining = NV_FALSE,
|
||||
},
|
||||
.alloc_stack = nvidia_modeset_rm_ops_alloc_stack,
|
||||
.free_stack = nvidia_modeset_rm_ops_free_stack,
|
||||
.enumerate_gpus = nvidia_modeset_enumerate_gpus,
|
||||
.open_gpu = nvidia_dev_get,
|
||||
.close_gpu = nvidia_dev_put,
|
||||
.op = rm_kernel_rmapi_op, /* provided by nv-kernel.o */
|
||||
.set_callbacks = nvidia_modeset_set_callbacks,
|
||||
};
|
||||
|
||||
if (strcmp(rm_ops->version_string, NV_VERSION_STRING) != 0)
|
||||
{
|
||||
rm_ops->version_string = NV_VERSION_STRING;
|
||||
return NV_ERR_GENERIC;
|
||||
}
|
||||
|
||||
*rm_ops = local_rm_ops;
|
||||
|
||||
if (NV_ALLOW_WRITE_COMBINING(NV_MEMORY_TYPE_FRAMEBUFFER)) {
|
||||
rm_ops->system_info.allow_write_combining = NV_TRUE;
|
||||
}
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(nvidia_get_rm_ops);
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nv-msi.h"
|
||||
#include "nv-proto.h"
|
||||
|
||||
#if defined(NV_LINUX_PCIE_MSI_SUPPORTED)
|
||||
void NV_API_CALL nv_init_msi(nv_state_t *nv)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
int rc = 0;
|
||||
|
||||
rc = pci_enable_msi(nvl->pci_dev);
|
||||
if (rc == 0)
|
||||
{
|
||||
nv->interrupt_line = nvl->pci_dev->irq;
|
||||
nv->flags |= NV_FLAG_USES_MSI;
|
||||
nvl->num_intr = 1;
|
||||
NV_KZALLOC(nvl->irq_count, sizeof(nv_irq_count_info_t) * nvl->num_intr);
|
||||
|
||||
if (nvl->irq_count == NULL)
|
||||
{
|
||||
nv->flags &= ~NV_FLAG_USES_MSI;
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv,
|
||||
"Failed to allocate counter for MSI entry; "
|
||||
"falling back to PCIe virtual-wire interrupts.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
nvl->current_num_irq_tracked = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nv->flags &= ~NV_FLAG_USES_MSI;
|
||||
if (nvl->pci_dev->irq != 0)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv,
|
||||
"Failed to enable MSI; "
|
||||
"falling back to PCIe virtual-wire interrupts.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void NV_API_CALL nv_init_msix(nv_state_t *nv)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
int num_intr = 0;
|
||||
struct msix_entry *msix_entries;
|
||||
int rc = 0;
|
||||
int i;
|
||||
|
||||
NV_SPIN_LOCK_INIT(&nvl->msix_isr_lock);
|
||||
|
||||
rc = os_alloc_mutex(&nvl->msix_bh_mutex);
|
||||
if (rc != 0)
|
||||
goto failed;
|
||||
|
||||
num_intr = nv_get_max_irq(nvl->pci_dev);
|
||||
|
||||
if (num_intr > NV_RM_MAX_MSIX_LINES)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_INFO, nv, "Reducing MSI-X count from %d to the "
|
||||
"driver-supported maximum %d.\n", num_intr, NV_RM_MAX_MSIX_LINES);
|
||||
num_intr = NV_RM_MAX_MSIX_LINES;
|
||||
}
|
||||
|
||||
NV_KMALLOC(nvl->msix_entries, sizeof(struct msix_entry) * num_intr);
|
||||
if (nvl->msix_entries == NULL)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv, "Failed to allocate MSI-X entries.\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for (i = 0, msix_entries = nvl->msix_entries; i < num_intr; i++, msix_entries++)
|
||||
{
|
||||
msix_entries->entry = i;
|
||||
}
|
||||
|
||||
NV_KZALLOC(nvl->irq_count, sizeof(nv_irq_count_info_t) * num_intr);
|
||||
|
||||
if (nvl->irq_count == NULL)
|
||||
{
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv, "Failed to allocate counter for MSI-X entries.\n");
|
||||
goto failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvl->current_num_irq_tracked = 0;
|
||||
}
|
||||
rc = nv_pci_enable_msix(nvl, num_intr);
|
||||
if (rc != NV_OK)
|
||||
goto failed;
|
||||
|
||||
nv->flags |= NV_FLAG_USES_MSIX;
|
||||
return;
|
||||
|
||||
failed:
|
||||
nv->flags &= ~NV_FLAG_USES_MSIX;
|
||||
|
||||
if (nvl->msix_entries)
|
||||
{
|
||||
NV_KFREE(nvl->msix_entries, sizeof(struct msix_entry) * num_intr);
|
||||
}
|
||||
|
||||
if (nvl->irq_count)
|
||||
{
|
||||
NV_KFREE(nvl->irq_count, sizeof(nv_irq_count_info_t) * num_intr);
|
||||
}
|
||||
|
||||
if (nvl->msix_bh_mutex)
|
||||
{
|
||||
os_free_mutex(nvl->msix_bh_mutex);
|
||||
nvl->msix_bh_mutex = NULL;
|
||||
}
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv, "Failed to enable MSI-X.\n");
|
||||
}
|
||||
|
||||
NvS32 NV_API_CALL nv_request_msix_irq(nv_linux_state_t *nvl)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
struct msix_entry *msix_entries;
|
||||
int rc = NV_ERR_INVALID_ARGUMENT;
|
||||
nv_state_t *nv = NV_STATE_PTR(nvl);
|
||||
|
||||
for (i = 0, msix_entries = nvl->msix_entries; i < nvl->num_intr;
|
||||
i++, msix_entries++)
|
||||
{
|
||||
rc = request_threaded_irq(msix_entries->vector, nvidia_isr_msix,
|
||||
nvidia_isr_msix_kthread_bh, nv_default_irq_flags(nv),
|
||||
nv_device_name, (void *)nvl);
|
||||
if (rc)
|
||||
{
|
||||
for( j = 0; j < i; j++)
|
||||
{
|
||||
free_irq(nvl->msix_entries[j].vector, (void *)nvl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2020-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include <linux/kernel.h> // For container_of
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/timer.h>
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
#if !defined(NVCPU_PPC64LE)
|
||||
#define NV_NANO_TIMER_USE_HRTIMER 1
|
||||
#else
|
||||
#define NV_NANO_TIMER_USE_HRTIMER 0
|
||||
#endif // !defined(NVCPU_PPC64LE)
|
||||
|
||||
struct nv_nano_timer
|
||||
{
|
||||
#if NV_NANO_TIMER_USE_HRTIMER
|
||||
struct hrtimer hr_timer; // This parameter holds linux high resolution timer object
|
||||
// can get replaced with platform specific timer object
|
||||
#else
|
||||
struct timer_list jiffy_timer;
|
||||
#endif
|
||||
nv_linux_state_t *nv_linux_state;
|
||||
void (*nv_nano_timer_callback)(struct nv_nano_timer *nv_nstimer);
|
||||
void *pTmrEvent;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief runs nano second resolution timer callback
|
||||
*
|
||||
* @param[in] nv_nstimer Pointer to nv_nano_timer_t object
|
||||
*/
|
||||
static void
|
||||
nvidia_nano_timer_callback(
|
||||
nv_nano_timer_t *nv_nstimer)
|
||||
{
|
||||
nv_state_t *nv = NULL;
|
||||
nv_linux_state_t *nvl = nv_nstimer->nv_linux_state;
|
||||
nvidia_stack_t *sp = NULL;
|
||||
|
||||
if (nv_kmem_cache_alloc_stack(&sp) != 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "NVRM: no cache memory \n");
|
||||
return;
|
||||
}
|
||||
|
||||
nv = NV_STATE_PTR(nvl);
|
||||
|
||||
if (rm_run_nano_timer_callback(sp, nv, nv_nstimer->pTmrEvent) != NV_OK)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "NVRM: Error in service of callback \n");
|
||||
}
|
||||
|
||||
nv_kmem_cache_free_stack(sp);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Allocates nano second resolution timer object
|
||||
*
|
||||
* @returns nv_nano_timer_t allocated pointer
|
||||
*/
|
||||
static nv_nano_timer_t *nv_alloc_nano_timer(void)
|
||||
{
|
||||
nv_nano_timer_t *nv_nstimer;
|
||||
|
||||
NV_KMALLOC(nv_nstimer, sizeof(nv_nano_timer_t));
|
||||
|
||||
if (nv_nstimer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(nv_nstimer, 0, sizeof(nv_nano_timer_t));
|
||||
|
||||
return nv_nstimer;
|
||||
}
|
||||
|
||||
#if NV_NANO_TIMER_USE_HRTIMER
|
||||
static enum hrtimer_restart nv_nano_timer_callback_typed_data(struct hrtimer *hrtmr)
|
||||
{
|
||||
struct nv_nano_timer *nv_nstimer =
|
||||
container_of(hrtmr, struct nv_nano_timer, hr_timer);
|
||||
|
||||
nv_nstimer->nv_nano_timer_callback(nv_nstimer);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
#else
|
||||
static inline void nv_jiffy_timer_callback_typed_data(struct timer_list *timer)
|
||||
{
|
||||
struct nv_nano_timer *nv_nstimer =
|
||||
container_of(timer, struct nv_nano_timer, jiffy_timer);
|
||||
|
||||
nv_nstimer->nv_nano_timer_callback(nv_nstimer);
|
||||
}
|
||||
|
||||
static inline void nv_jiffy_timer_callback_anon_data(unsigned long arg)
|
||||
{
|
||||
struct nv_nano_timer *nv_nstimer = (struct nv_nano_timer *)arg;
|
||||
|
||||
nv_nstimer->nv_nano_timer_callback(nv_nstimer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Creates & initializes nano second resolution timer object
|
||||
*
|
||||
* @param[in] nv Per gpu linux state
|
||||
* @param[in] tmrEvent pointer to TMR_EVENT
|
||||
* @param[in] nv_nstimer Pointer to nv_nano_timer_t object
|
||||
*/
|
||||
void NV_API_CALL nv_create_nano_timer(
|
||||
nv_state_t *nv,
|
||||
void *pTmrEvent,
|
||||
nv_nano_timer_t **pnv_nstimer)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
nv_nano_timer_t *nv_nstimer = nv_alloc_nano_timer();
|
||||
|
||||
if (nv_nstimer == NULL)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS, "NVRM: Not able to create timer object \n");
|
||||
*pnv_nstimer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
nv_nstimer->nv_linux_state = nvl;
|
||||
nv_nstimer->pTmrEvent = pTmrEvent;
|
||||
|
||||
nv_nstimer->nv_nano_timer_callback = nvidia_nano_timer_callback;
|
||||
|
||||
#if NV_NANO_TIMER_USE_HRTIMER
|
||||
hrtimer_init(&nv_nstimer->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
nv_nstimer->hr_timer.function = nv_nano_timer_callback_typed_data;
|
||||
#else
|
||||
#if defined(NV_TIMER_SETUP_PRESENT)
|
||||
timer_setup(&nv_nstimer->jiffy_timer, nv_jiffy_timer_callback_typed_data, 0);
|
||||
#else
|
||||
init_timer(&nv_nstimer->jiffy_timer);
|
||||
nv_nstimer->jiffy_timer.function = nv_jiffy_timer_callback_anon_data;
|
||||
nv_nstimer->jiffy_timer.data = (unsigned long)nv_nstimer;
|
||||
#endif // NV_TIMER_SETUP_PRESENT
|
||||
#endif // NV_NANO_TIMER_USE_HRTIMER
|
||||
|
||||
*pnv_nstimer = nv_nstimer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Starts nano second resolution timer
|
||||
*
|
||||
* @param[in] nv Per gpu linux state
|
||||
* @param[in] nv_nstimer Pointer to nv_nano_timer_t object
|
||||
* @param[in] time_ns Relative time in nano seconds
|
||||
*/
|
||||
void NV_API_CALL nv_start_nano_timer(
|
||||
nv_state_t *nv,
|
||||
nv_nano_timer_t *nv_nstimer,
|
||||
NvU64 time_ns)
|
||||
{
|
||||
#if NV_NANO_TIMER_USE_HRTIMER
|
||||
ktime_t ktime = ktime_set(0, time_ns);
|
||||
hrtimer_start(&nv_nstimer->hr_timer, ktime, HRTIMER_MODE_REL);
|
||||
#else
|
||||
unsigned long time_jiffies;
|
||||
NvU32 time_us;
|
||||
|
||||
time_us = (NvU32)(time_ns / 1000);
|
||||
|
||||
if (time_us == 0)
|
||||
{
|
||||
nv_printf(NV_DBG_WARNINGS, "NVRM: Timer value cannot be less than 1 usec.\n");
|
||||
}
|
||||
|
||||
time_jiffies = usecs_to_jiffies(time_us);
|
||||
mod_timer(&nv_nstimer->jiffy_timer, jiffies + time_jiffies);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Cancels nano second resolution timer
|
||||
*
|
||||
* @param[in] nv Per gpu linux state
|
||||
* @param[in] nv_nstimer Pointer to nv_nano_timer_t object
|
||||
*/
|
||||
void NV_API_CALL nv_cancel_nano_timer(
|
||||
nv_state_t *nv,
|
||||
nv_nano_timer_t *nv_nstimer)
|
||||
{
|
||||
#if NV_NANO_TIMER_USE_HRTIMER
|
||||
hrtimer_cancel(&nv_nstimer->hr_timer);
|
||||
#else
|
||||
del_timer_sync(&nv_nstimer->jiffy_timer);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Cancels & deletes nano second resolution timer object
|
||||
*
|
||||
* @param[in] nv Per gpu linux state
|
||||
* @param[in] nv_nstimer Pointer to nv_nano_timer_t object
|
||||
*/
|
||||
void NV_API_CALL nv_destroy_nano_timer(
|
||||
nv_state_t *nv,
|
||||
nv_nano_timer_t *nv_nstimer)
|
||||
{
|
||||
nv_cancel_nano_timer(nv, nv_nstimer);
|
||||
NV_KFREE(nv_nstimer, sizeof(nv_nano_timer_t));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2011-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NV_P2P_H_
|
||||
#define _NV_P2P_H_
|
||||
|
||||
/*
|
||||
* NVIDIA P2P Structure Versioning
|
||||
*
|
||||
* For the nvidia_p2p_*_t structures allocated by the NVIDIA driver, it will
|
||||
* set the version field of the structure according to the definition used by
|
||||
* the NVIDIA driver. The "major" field of the version is defined as the upper
|
||||
* 16 bits, and the "minor" field of the version is defined as the lower 16
|
||||
* bits. The version field will always be the first 4 bytes of the structure,
|
||||
* and third-party drivers should check the value of this field in structures
|
||||
* allocated by the NVIDIA driver to ensure runtime compatibility.
|
||||
*
|
||||
* In general, version numbers will be incremented as follows:
|
||||
* - When a backwards-compatible change is made to the structure layout, the
|
||||
* minor version for that structure will be incremented. Third-party drivers
|
||||
* built against an older minor version will continue to work with the newer
|
||||
* minor version used by the NVIDIA driver, without recompilation.
|
||||
* - When a breaking change is made to the structure layout, the major version
|
||||
* will be incremented. Third-party drivers built against an older major
|
||||
* version require at least recompilation and potentially additional updates
|
||||
* to use the new API.
|
||||
*/
|
||||
#define NVIDIA_P2P_MAJOR_VERSION_MASK 0xffff0000
|
||||
#define NVIDIA_P2P_MINOR_VERSION_MASK 0x0000ffff
|
||||
|
||||
#define NVIDIA_P2P_MAJOR_VERSION(v) \
|
||||
(((v) & NVIDIA_P2P_MAJOR_VERSION_MASK) >> 16)
|
||||
|
||||
#define NVIDIA_P2P_MINOR_VERSION(v) \
|
||||
(((v) & NVIDIA_P2P_MINOR_VERSION_MASK))
|
||||
|
||||
#define NVIDIA_P2P_MAJOR_VERSION_MATCHES(p, v) \
|
||||
(NVIDIA_P2P_MAJOR_VERSION((p)->version) == NVIDIA_P2P_MAJOR_VERSION(v))
|
||||
|
||||
#define NVIDIA_P2P_VERSION_COMPATIBLE(p, v) \
|
||||
(NVIDIA_P2P_MAJOR_VERSION_MATCHES(p, v) && \
|
||||
(NVIDIA_P2P_MINOR_VERSION((p)->version) >= (NVIDIA_P2P_MINOR_VERSION(v))))
|
||||
|
||||
enum {
|
||||
NVIDIA_P2P_ARCHITECTURE_TESLA = 0,
|
||||
NVIDIA_P2P_ARCHITECTURE_FERMI,
|
||||
NVIDIA_P2P_ARCHITECTURE_CURRENT = NVIDIA_P2P_ARCHITECTURE_FERMI
|
||||
};
|
||||
|
||||
#define NVIDIA_P2P_PARAMS_VERSION 0x00010001
|
||||
|
||||
enum {
|
||||
NVIDIA_P2P_PARAMS_ADDRESS_INDEX_GPU = 0,
|
||||
NVIDIA_P2P_PARAMS_ADDRESS_INDEX_THIRD_PARTY_DEVICE,
|
||||
NVIDIA_P2P_PARAMS_ADDRESS_INDEX_MAX = \
|
||||
NVIDIA_P2P_PARAMS_ADDRESS_INDEX_THIRD_PARTY_DEVICE
|
||||
};
|
||||
|
||||
#define NVIDIA_P2P_GPU_UUID_LEN 16
|
||||
|
||||
typedef
|
||||
struct nvidia_p2p_params {
|
||||
uint32_t version;
|
||||
uint32_t architecture;
|
||||
union nvidia_p2p_mailbox_addresses {
|
||||
struct {
|
||||
uint64_t wmb_addr;
|
||||
uint64_t wmb_data;
|
||||
uint64_t rreq_addr;
|
||||
uint64_t rcomp_addr;
|
||||
uint64_t reserved[2];
|
||||
} fermi;
|
||||
} addresses[NVIDIA_P2P_PARAMS_ADDRESS_INDEX_MAX+1];
|
||||
} nvidia_p2p_params_t;
|
||||
|
||||
/*
|
||||
* Macro for users to detect
|
||||
* driver support for persistent pages.
|
||||
*/
|
||||
#define NVIDIA_P2P_CAP_GET_PAGES_PERSISTENT_API
|
||||
|
||||
/*
|
||||
* This API is not supported.
|
||||
*/
|
||||
int nvidia_p2p_init_mapping(uint64_t p2p_token,
|
||||
struct nvidia_p2p_params *params,
|
||||
void (*destroy_callback)(void *data),
|
||||
void *data);
|
||||
|
||||
/*
|
||||
* This API is not supported.
|
||||
*/
|
||||
int nvidia_p2p_destroy_mapping(uint64_t p2p_token);
|
||||
|
||||
enum nvidia_p2p_page_size_type {
|
||||
NVIDIA_P2P_PAGE_SIZE_4KB = 0,
|
||||
NVIDIA_P2P_PAGE_SIZE_64KB,
|
||||
NVIDIA_P2P_PAGE_SIZE_128KB,
|
||||
NVIDIA_P2P_PAGE_SIZE_COUNT
|
||||
};
|
||||
|
||||
typedef
|
||||
struct nvidia_p2p_page {
|
||||
uint64_t physical_address;
|
||||
union nvidia_p2p_request_registers {
|
||||
struct {
|
||||
uint32_t wreqmb_h;
|
||||
uint32_t rreqmb_h;
|
||||
uint32_t rreqmb_0;
|
||||
uint32_t reserved[3];
|
||||
} fermi;
|
||||
} registers;
|
||||
} nvidia_p2p_page_t;
|
||||
|
||||
#define NVIDIA_P2P_PAGE_TABLE_VERSION 0x00010002
|
||||
|
||||
#define NVIDIA_P2P_PAGE_TABLE_VERSION_COMPATIBLE(p) \
|
||||
NVIDIA_P2P_VERSION_COMPATIBLE(p, NVIDIA_P2P_PAGE_TABLE_VERSION)
|
||||
|
||||
typedef
|
||||
struct nvidia_p2p_page_table {
|
||||
uint32_t version;
|
||||
uint32_t page_size; /* enum nvidia_p2p_page_size_type */
|
||||
struct nvidia_p2p_page **pages;
|
||||
uint32_t entries;
|
||||
uint8_t *gpu_uuid;
|
||||
} nvidia_p2p_page_table_t;
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Make the pages underlying a range of GPU virtual memory
|
||||
* accessible to a third-party device.
|
||||
*
|
||||
* This API only supports pinned, GPU-resident memory, such as that provided
|
||||
* by cudaMalloc().
|
||||
*
|
||||
* This API may sleep.
|
||||
*
|
||||
* @param[in] p2p_token
|
||||
* A token that uniquely identifies the P2P mapping.
|
||||
* @param[in] va_space
|
||||
* A GPU virtual address space qualifier.
|
||||
* @param[in] virtual_address
|
||||
* The start address in the specified virtual address space.
|
||||
* Address must be aligned to the 64KB boundary.
|
||||
* @param[in] length
|
||||
* The length of the requested P2P mapping.
|
||||
* Length must be a multiple of 64KB.
|
||||
* @param[out] page_table
|
||||
* A pointer to an array of structures with P2P PTEs.
|
||||
* @param[in] free_callback
|
||||
* A pointer to the function to be invoked when the pages
|
||||
* underlying the virtual address range are freed
|
||||
* implicitly.
|
||||
* @param[in] data
|
||||
* A non-NULL opaque pointer to private data to be passed to the
|
||||
* callback function.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
* -ENOTSUPP if the requested operation is not supported.
|
||||
* -ENOMEM if the driver failed to allocate memory or if
|
||||
* insufficient resources were available to complete the operation.
|
||||
* -EIO if an unknown error occurred.
|
||||
*/
|
||||
int nvidia_p2p_get_pages( uint64_t p2p_token, uint32_t va_space,
|
||||
uint64_t virtual_address, uint64_t length,
|
||||
struct nvidia_p2p_page_table **page_table,
|
||||
void (*free_callback)(void *data), void *data);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Pin and make the pages underlying a range of GPU virtual memory
|
||||
* accessible to a third-party device. The pages will persist until
|
||||
* explicitly freed by nvidia_p2p_put_pages_persistent().
|
||||
*
|
||||
* Persistent GPU memory mappings are not supported on PowerPC,
|
||||
* MIG-enabled devices and vGPU.
|
||||
*
|
||||
* This API only supports pinned, GPU-resident memory, such as that provided
|
||||
* by cudaMalloc().
|
||||
*
|
||||
* This API may sleep.
|
||||
*
|
||||
* @param[in] virtual_address
|
||||
* The start address in the specified virtual address space.
|
||||
* Address must be aligned to the 64KB boundary.
|
||||
* @param[in] length
|
||||
* The length of the requested P2P mapping.
|
||||
* Length must be a multiple of 64KB.
|
||||
* @param[out] page_table
|
||||
* A pointer to an array of structures with P2P PTEs.
|
||||
* @param[in] flags
|
||||
* Must be set to zero for now.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
* -ENOTSUPP if the requested operation is not supported.
|
||||
* -ENOMEM if the driver failed to allocate memory or if
|
||||
* insufficient resources were available to complete the operation.
|
||||
* -EIO if an unknown error occurred.
|
||||
*/
|
||||
int nvidia_p2p_get_pages_persistent(uint64_t virtual_address,
|
||||
uint64_t length,
|
||||
struct nvidia_p2p_page_table **page_table,
|
||||
uint32_t flags);
|
||||
|
||||
#define NVIDIA_P2P_DMA_MAPPING_VERSION 0x00020003
|
||||
|
||||
#define NVIDIA_P2P_DMA_MAPPING_VERSION_COMPATIBLE(p) \
|
||||
NVIDIA_P2P_VERSION_COMPATIBLE(p, NVIDIA_P2P_DMA_MAPPING_VERSION)
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
typedef
|
||||
struct nvidia_p2p_dma_mapping {
|
||||
uint32_t version;
|
||||
enum nvidia_p2p_page_size_type page_size_type;
|
||||
uint32_t entries;
|
||||
uint64_t *dma_addresses;
|
||||
void *private;
|
||||
struct pci_dev *pci_dev;
|
||||
} nvidia_p2p_dma_mapping_t;
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Make the physical pages retrieved using nvidia_p2p_get_pages accessible to
|
||||
* a third-party device.
|
||||
*
|
||||
* @param[in] peer
|
||||
* The struct pci_dev * of the peer device that needs to DMA to/from the
|
||||
* mapping.
|
||||
* @param[in] page_table
|
||||
* The page table outlining the physical pages underlying the mapping, as
|
||||
* retrieved with nvidia_p2p_get_pages().
|
||||
* @param[out] dma_mapping
|
||||
* The DMA mapping containing the DMA addresses to use on the third-party
|
||||
* device.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
* -ENOTSUPP if the requested operation is not supported.
|
||||
* -EIO if an unknown error occurred.
|
||||
*/
|
||||
int nvidia_p2p_dma_map_pages(struct pci_dev *peer,
|
||||
struct nvidia_p2p_page_table *page_table,
|
||||
struct nvidia_p2p_dma_mapping **dma_mapping);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Unmap the physical pages previously mapped to the third-party device by
|
||||
* nvidia_p2p_dma_map_pages().
|
||||
*
|
||||
* @param[in] peer
|
||||
* The struct pci_dev * of the peer device that the DMA mapping belongs to.
|
||||
* @param[in] page_table
|
||||
* The page table backing the DMA mapping to be unmapped.
|
||||
* @param[in] dma_mapping
|
||||
* The DMA mapping containing the DMA addresses used by the third-party
|
||||
* device, as retrieved with nvidia_p2p_dma_map_pages(). After this call
|
||||
* returns, neither this struct nor the addresses contained within will be
|
||||
* valid for use by the third-party device.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
* -EIO if an unknown error occurred.
|
||||
*/
|
||||
int nvidia_p2p_dma_unmap_pages(struct pci_dev *peer,
|
||||
struct nvidia_p2p_page_table *page_table,
|
||||
struct nvidia_p2p_dma_mapping *dma_mapping);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Release a set of pages previously made accessible to
|
||||
* a third-party device.
|
||||
*
|
||||
* This API may sleep.
|
||||
*
|
||||
* @param[in] p2p_token
|
||||
* A token that uniquely identifies the P2P mapping.
|
||||
* @param[in] va_space
|
||||
* A GPU virtual address space qualifier.
|
||||
* @param[in] virtual_address
|
||||
* The start address in the specified virtual address space.
|
||||
* @param[in] page_table
|
||||
* A pointer to the array of structures with P2P PTEs.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
* -EIO if an unknown error occurred.
|
||||
*/
|
||||
int nvidia_p2p_put_pages(uint64_t p2p_token,
|
||||
uint32_t va_space, uint64_t virtual_address,
|
||||
struct nvidia_p2p_page_table *page_table);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Release a set of persistent pages previously made accessible to
|
||||
* a third-party device.
|
||||
*
|
||||
* This API may sleep.
|
||||
*
|
||||
* @param[in] virtual_address
|
||||
* The start address in the specified virtual address space.
|
||||
* @param[in] page_table
|
||||
* A pointer to the array of structures with P2P PTEs.
|
||||
* @param[in] flags
|
||||
* Must be set to zero for now.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
* -EIO if an unknown error occurred.
|
||||
*/
|
||||
int nvidia_p2p_put_pages_persistent(uint64_t virtual_address,
|
||||
struct nvidia_p2p_page_table *page_table,
|
||||
uint32_t flags);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Free a third-party P2P page table. (This function is a no-op.)
|
||||
*
|
||||
* @param[in] page_table
|
||||
* A pointer to the array of structures with P2P PTEs.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
*/
|
||||
int nvidia_p2p_free_page_table(struct nvidia_p2p_page_table *page_table);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Free a third-party P2P DMA mapping. (This function is a no-op.)
|
||||
*
|
||||
* @param[in] dma_mapping
|
||||
* A pointer to the DMA mapping structure.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL if an invalid argument was supplied.
|
||||
*/
|
||||
int nvidia_p2p_free_dma_mapping(struct nvidia_p2p_dma_mapping *dma_mapping);
|
||||
|
||||
#define NVIDIA_P2P_RSYNC_DRIVER_VERSION 0x00010001
|
||||
|
||||
#define NVIDIA_P2P_RSYNC_DRIVER_VERSION_COMPATIBLE(p) \
|
||||
NVIDIA_P2P_VERSION_COMPATIBLE(p, NVIDIA_P2P_RSYNC_DRIVER_VERSION)
|
||||
|
||||
typedef
|
||||
struct nvidia_p2p_rsync_driver {
|
||||
uint32_t version;
|
||||
int (*get_relaxed_ordering_mode)(int *mode, void *data);
|
||||
void (*put_relaxed_ordering_mode)(int mode, void *data);
|
||||
void (*wait_for_rsync)(struct pci_dev *gpu, void *data);
|
||||
} nvidia_p2p_rsync_driver_t;
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Registers the rsync driver.
|
||||
*
|
||||
* @param[in] driver
|
||||
* A pointer to the rsync driver structure. The NVIDIA driver would use,
|
||||
*
|
||||
* get_relaxed_ordering_mode to obtain a reference to the current relaxed
|
||||
* ordering mode (treated as a boolean) from the rsync driver.
|
||||
*
|
||||
* put_relaxed_ordering_mode to release a reference to the current relaxed
|
||||
* ordering mode back to the rsync driver. The NVIDIA driver will call this
|
||||
* function once for each successful call to get_relaxed_ordering_mode, and
|
||||
* the relaxed ordering mode must not change until the last reference is
|
||||
* released.
|
||||
*
|
||||
* wait_for_rsync to call into the rsync module to issue RSYNC. This callback
|
||||
* can't sleep or re-schedule as it may arrive under spinlocks.
|
||||
* @param[in] data
|
||||
* A pointer to the rsync driver's private data.
|
||||
*
|
||||
* @Returns
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL parameters are incorrect.
|
||||
* -EBUSY if a module is already registered or GPU devices are in use.
|
||||
*/
|
||||
int nvidia_p2p_register_rsync_driver(nvidia_p2p_rsync_driver_t *driver,
|
||||
void *data);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Unregisters the rsync driver.
|
||||
*
|
||||
* @param[in] driver
|
||||
* A pointer to the rsync driver structure.
|
||||
* @param[in] data
|
||||
* A pointer to the rsync driver's private data.
|
||||
*/
|
||||
void nvidia_p2p_unregister_rsync_driver(nvidia_p2p_rsync_driver_t *driver,
|
||||
void *data);
|
||||
|
||||
#define NVIDIA_P2P_RSYNC_REG_INFO_VERSION 0x00020001
|
||||
|
||||
#define NVIDIA_P2P_RSYNC_REG_INFO_VERSION_COMPATIBLE(p) \
|
||||
NVIDIA_P2P_VERSION_COMPATIBLE(p, NVIDIA_P2P_RSYNC_REG_INFO_VERSION)
|
||||
|
||||
typedef struct nvidia_p2p_rsync_reg {
|
||||
void *ptr;
|
||||
size_t size;
|
||||
struct pci_dev *ibmnpu;
|
||||
struct pci_dev *gpu;
|
||||
uint32_t cluster_id;
|
||||
uint32_t socket_id;
|
||||
} nvidia_p2p_rsync_reg_t;
|
||||
|
||||
typedef struct nvidia_p2p_rsync_reg_info {
|
||||
uint32_t version;
|
||||
nvidia_p2p_rsync_reg_t *regs;
|
||||
size_t entries;
|
||||
} nvidia_p2p_rsync_reg_info_t;
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Gets rsync (GEN-ID) register information associated with the supported
|
||||
* NPUs.
|
||||
*
|
||||
* The caller would use the returned information {GPU device, NPU device,
|
||||
* socket-id, cluster-id} to pick the optimal generation registers to issue
|
||||
* RSYNC (NVLink HW flush).
|
||||
*
|
||||
* The interface allocates structures to return the information, hence
|
||||
* nvidia_p2p_put_rsync_registers() must be called to free the structures.
|
||||
*
|
||||
* Note, cluster-id is hardcoded to zero as early system configurations would
|
||||
* only support cluster mode i.e. all devices would share the same cluster-id
|
||||
* (0). In the future, appropriate kernel support would be needed to query
|
||||
* cluster-ids.
|
||||
*
|
||||
* @param[out] reg_info
|
||||
* A pointer to the rsync reg info structure.
|
||||
*
|
||||
* @Returns
|
||||
* 0 Upon successful completion. Otherwise, returns negative value.
|
||||
*/
|
||||
int nvidia_p2p_get_rsync_registers(nvidia_p2p_rsync_reg_info_t **reg_info);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Frees the structures allocated by nvidia_p2p_get_rsync_registers().
|
||||
*
|
||||
* @param[in] reg_info
|
||||
* A pointer to the rsync reg info structure.
|
||||
*/
|
||||
void nvidia_p2p_put_rsync_registers(nvidia_p2p_rsync_reg_info_t *reg_info);
|
||||
|
||||
#endif /* _NV_P2P_H_ */
|
||||
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-reg.h"
|
||||
#include "nv-pat.h"
|
||||
|
||||
int nv_pat_mode = NV_PAT_MODE_DISABLED;
|
||||
|
||||
#if defined(NV_ENABLE_PAT_SUPPORT)
|
||||
/*
|
||||
* Private PAT support for use by the NVIDIA driver. This is used on
|
||||
* kernels that do not modify the PAT to include a write-combining
|
||||
* entry.
|
||||
*
|
||||
* On kernels that have CONFIG_X86_PAT, the NVIDIA driver still checks that the
|
||||
* WC entry is as expected before using PAT.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_X86_PAT)
|
||||
#define NV_ENABLE_BUILTIN_PAT_SUPPORT 0
|
||||
#else
|
||||
#define NV_ENABLE_BUILTIN_PAT_SUPPORT 1
|
||||
#endif
|
||||
|
||||
|
||||
#define NV_READ_PAT_ENTRIES(pat1, pat2) rdmsr(0x277, (pat1), (pat2))
|
||||
#define NV_WRITE_PAT_ENTRIES(pat1, pat2) wrmsr(0x277, (pat1), (pat2))
|
||||
#define NV_PAT_ENTRY(pat, index) \
|
||||
(((pat) & (0xff << ((index)*8))) >> ((index)*8))
|
||||
|
||||
#if NV_ENABLE_BUILTIN_PAT_SUPPORT
|
||||
|
||||
static unsigned long orig_pat1, orig_pat2;
|
||||
|
||||
static inline void nv_disable_caches(unsigned long *cr4)
|
||||
{
|
||||
unsigned long cr0 = read_cr0();
|
||||
write_cr0(((cr0 & (0xdfffffff)) | 0x40000000));
|
||||
wbinvd();
|
||||
*cr4 = NV_READ_CR4();
|
||||
if (*cr4 & 0x80) NV_WRITE_CR4(*cr4 & ~0x80);
|
||||
__flush_tlb();
|
||||
}
|
||||
|
||||
static inline void nv_enable_caches(unsigned long cr4)
|
||||
{
|
||||
unsigned long cr0 = read_cr0();
|
||||
wbinvd();
|
||||
__flush_tlb();
|
||||
write_cr0((cr0 & 0x9fffffff));
|
||||
if (cr4 & 0x80) NV_WRITE_CR4(cr4);
|
||||
}
|
||||
|
||||
static void nv_setup_pat_entries(void *info)
|
||||
{
|
||||
unsigned long pat1, pat2, cr4;
|
||||
unsigned long eflags;
|
||||
|
||||
#if defined(NV_ENABLE_HOTPLUG_CPU)
|
||||
int cpu = (NvUPtr)info;
|
||||
if ((cpu != 0) && (cpu != (int)smp_processor_id()))
|
||||
return;
|
||||
#endif
|
||||
|
||||
NV_SAVE_FLAGS(eflags);
|
||||
NV_CLI();
|
||||
nv_disable_caches(&cr4);
|
||||
|
||||
NV_READ_PAT_ENTRIES(pat1, pat2);
|
||||
|
||||
pat1 &= 0xffff00ff;
|
||||
pat1 |= 0x00000100;
|
||||
|
||||
NV_WRITE_PAT_ENTRIES(pat1, pat2);
|
||||
|
||||
nv_enable_caches(cr4);
|
||||
NV_RESTORE_FLAGS(eflags);
|
||||
}
|
||||
|
||||
static void nv_restore_pat_entries(void *info)
|
||||
{
|
||||
unsigned long cr4;
|
||||
unsigned long eflags;
|
||||
|
||||
#if defined(NV_ENABLE_HOTPLUG_CPU)
|
||||
int cpu = (NvUPtr)info;
|
||||
if ((cpu != 0) && (cpu != (int)smp_processor_id()))
|
||||
return;
|
||||
#endif
|
||||
|
||||
NV_SAVE_FLAGS(eflags);
|
||||
NV_CLI();
|
||||
nv_disable_caches(&cr4);
|
||||
|
||||
NV_WRITE_PAT_ENTRIES(orig_pat1, orig_pat2);
|
||||
|
||||
nv_enable_caches(cr4);
|
||||
NV_RESTORE_FLAGS(eflags);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE 1:
|
||||
* Functions register_cpu_notifier(), unregister_cpu_notifier(),
|
||||
* macros register_hotcpu_notifier, register_hotcpu_notifier,
|
||||
* and CPU states CPU_DOWN_FAILED, CPU_DOWN_PREPARE
|
||||
* were removed by the following commit:
|
||||
* 2016 Dec 25: b272f732f888d4cf43c943a40c9aaa836f9b7431
|
||||
*
|
||||
* NV_REGISTER_CPU_NOTIFIER_PRESENT is true when
|
||||
* register_cpu_notifier() is present.
|
||||
*
|
||||
* The functions cpuhp_setup_state() and cpuhp_remove_state() should be
|
||||
* used as an alternative to register_cpu_notifier() and
|
||||
* unregister_cpu_notifier() functions. The following
|
||||
* commit introduced these functions as well as the enum cpuhp_state.
|
||||
* 2016 Feb 26: 5b7aa87e0482be768486e0c2277aa4122487eb9d
|
||||
*
|
||||
* NV_CPUHP_CPUHP_STATE_PRESENT is true when cpuhp_setup_state() is present.
|
||||
*
|
||||
* For kernels where both cpuhp_setup_state() and register_cpu_notifier()
|
||||
* are present, we still use register_cpu_notifier().
|
||||
*/
|
||||
|
||||
static int
|
||||
nvidia_cpu_teardown(unsigned int cpu)
|
||||
{
|
||||
#if defined(NV_ENABLE_HOTPLUG_CPU)
|
||||
unsigned int this_cpu = get_cpu();
|
||||
|
||||
if (this_cpu == cpu)
|
||||
nv_restore_pat_entries(NULL);
|
||||
else
|
||||
smp_call_function(nv_restore_pat_entries, &cpu, 1);
|
||||
|
||||
put_cpu();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvidia_cpu_online(unsigned int cpu)
|
||||
{
|
||||
#if defined(NV_ENABLE_HOTPLUG_CPU)
|
||||
unsigned int this_cpu = get_cpu();
|
||||
|
||||
if (this_cpu == cpu)
|
||||
nv_setup_pat_entries(NULL);
|
||||
else
|
||||
smp_call_function(nv_setup_pat_entries, &cpu, 1);
|
||||
|
||||
put_cpu();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nv_enable_builtin_pat_support(void)
|
||||
{
|
||||
unsigned long pat1, pat2;
|
||||
|
||||
NV_READ_PAT_ENTRIES(orig_pat1, orig_pat2);
|
||||
nv_printf(NV_DBG_SETUP, "saved orig pats as 0x%lx 0x%lx\n", orig_pat1, orig_pat2);
|
||||
|
||||
on_each_cpu(nv_setup_pat_entries, NULL, 1);
|
||||
|
||||
NV_READ_PAT_ENTRIES(pat1, pat2);
|
||||
nv_printf(NV_DBG_SETUP, "changed pats to 0x%lx 0x%lx\n", pat1, pat2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void nv_disable_builtin_pat_support(void)
|
||||
{
|
||||
unsigned long pat1, pat2;
|
||||
|
||||
on_each_cpu(nv_restore_pat_entries, NULL, 1);
|
||||
|
||||
nv_pat_mode = NV_PAT_MODE_DISABLED;
|
||||
|
||||
NV_READ_PAT_ENTRIES(pat1, pat2);
|
||||
nv_printf(NV_DBG_SETUP, "restored orig pats as 0x%lx 0x%lx\n", pat1, pat2);
|
||||
}
|
||||
|
||||
static int
|
||||
nvidia_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
/* CPU_DOWN_FAILED was added by the following commit
|
||||
* 2004 Oct 18: 71da3667be80d30121df3972caa0bf5684228379
|
||||
*
|
||||
* CPU_DOWN_PREPARE was added by the following commit
|
||||
* 2004 Oct 18: d13d28de21d913aacd3c91e76e307fa2eb7835d8
|
||||
*
|
||||
* We use one ifdef for both macros since they were added on the same day.
|
||||
*/
|
||||
#if defined(CPU_DOWN_FAILED)
|
||||
switch (action)
|
||||
{
|
||||
case CPU_DOWN_FAILED:
|
||||
case CPU_ONLINE:
|
||||
nvidia_cpu_online((NvUPtr)hcpu);
|
||||
break;
|
||||
case CPU_DOWN_PREPARE:
|
||||
nvidia_cpu_teardown((NvUPtr)hcpu);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* See NOTE 1.
|
||||
* In order to avoid warnings for unused variable when compiling against
|
||||
* kernel versions which include changes of commit id
|
||||
* b272f732f888d4cf43c943a40c9aaa836f9b7431, we have to protect declaration
|
||||
* of nv_hotcpu_nfb with #if.
|
||||
*
|
||||
* NV_REGISTER_CPU_NOTIFIER_PRESENT is checked before
|
||||
* NV_CPUHP_SETUP_STATE_PRESENT to avoid compilation warnings for unused
|
||||
* variable nvidia_pat_online for kernels where both
|
||||
* NV_REGISTER_CPU_NOTIFIER_PRESENT and NV_CPUHP_SETUP_STATE_PRESENT
|
||||
* are true.
|
||||
*/
|
||||
#if defined(NV_REGISTER_CPU_NOTIFIER_PRESENT) && defined(CONFIG_HOTPLUG_CPU)
|
||||
static struct notifier_block nv_hotcpu_nfb = {
|
||||
.notifier_call = nvidia_cpu_callback,
|
||||
.priority = 0
|
||||
};
|
||||
#elif defined(NV_CPUHP_SETUP_STATE_PRESENT)
|
||||
static enum cpuhp_state nvidia_pat_online;
|
||||
#endif
|
||||
|
||||
static int
|
||||
nvidia_register_cpu_hotplug_notifier(void)
|
||||
{
|
||||
int ret;
|
||||
/* See NOTE 1 */
|
||||
#if defined(NV_REGISTER_CPU_NOTIFIER_PRESENT) && defined(CONFIG_HOTPLUG_CPU)
|
||||
/* register_hotcpu_notiifer() returns 0 on success or -ENOENT on failure */
|
||||
ret = register_hotcpu_notifier(&nv_hotcpu_nfb);
|
||||
#elif defined(NV_CPUHP_SETUP_STATE_PRESENT)
|
||||
/*
|
||||
* cpuhp_setup_state() returns positive number on success when state is
|
||||
* CPUHP_AP_ONLINE_DYN. On failure, it returns a negative number.
|
||||
*/
|
||||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
|
||||
"nvidia/pat:online",
|
||||
nvidia_cpu_online,
|
||||
nvidia_cpu_teardown);
|
||||
if (ret < 0)
|
||||
{
|
||||
/*
|
||||
* If cpuhp_setup_state() fails, the cpuhp_remove_state()
|
||||
* should never be called. If it gets called, we might remove
|
||||
* some other state. Hence, explicitly set
|
||||
* nvidia_pat_online to zero. This will trigger a BUG()
|
||||
* in cpuhp_remove_state().
|
||||
*/
|
||||
nvidia_pat_online = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvidia_pat_online = ret;
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* This function should be a no-op for kernels which
|
||||
* - do not have CONFIG_HOTPLUG_CPU enabled,
|
||||
* - do not have PAT support,
|
||||
* - do not have the cpuhp_setup_state() function.
|
||||
*
|
||||
* On such kernels, returning an error here would result in module init
|
||||
* failure. Hence, return 0 here.
|
||||
*/
|
||||
if (nv_pat_mode == NV_PAT_MODE_BUILTIN)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
nv_disable_pat_support();
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: CPU hotplug notifier registration failed!\n");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvidia_unregister_cpu_hotplug_notifier(void)
|
||||
{
|
||||
/* See NOTE 1 */
|
||||
#if defined(NV_REGISTER_CPU_NOTIFIER_PRESENT) && defined(CONFIG_HOTPLUG_CPU)
|
||||
unregister_hotcpu_notifier(&nv_hotcpu_nfb);
|
||||
#elif defined(NV_CPUHP_SETUP_STATE_PRESENT)
|
||||
cpuhp_remove_state(nvidia_pat_online);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#else /* NV_ENABLE_BUILTIN_PAT_SUPPORT */
|
||||
|
||||
static int nv_enable_builtin_pat_support(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static void nv_disable_builtin_pat_support(void)
|
||||
{
|
||||
}
|
||||
static int nvidia_register_cpu_hotplug_notifier(void)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
static void nvidia_unregister_cpu_hotplug_notifier(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* NV_ENABLE_BUILTIN_PAT_SUPPORT */
|
||||
|
||||
static int nv_determine_pat_mode(void)
|
||||
{
|
||||
unsigned int pat1, pat2, i;
|
||||
NvU8 PAT_WC_index;
|
||||
|
||||
if (!test_bit(X86_FEATURE_PAT,
|
||||
(volatile unsigned long *)&boot_cpu_data.x86_capability))
|
||||
{
|
||||
if ((boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ||
|
||||
(boot_cpu_data.cpuid_level < 1) ||
|
||||
((cpuid_edx(1) & (1 << 16)) == 0) ||
|
||||
(boot_cpu_data.x86 != 6) || (boot_cpu_data.x86_model >= 15))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: CPU does not support the PAT.\n");
|
||||
return NV_PAT_MODE_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
NV_READ_PAT_ENTRIES(pat1, pat2);
|
||||
PAT_WC_index = 0xf;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (NV_PAT_ENTRY(pat1, i) == 0x01)
|
||||
{
|
||||
PAT_WC_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NV_PAT_ENTRY(pat2, i) == 0x01)
|
||||
{
|
||||
PAT_WC_index = (i + 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (PAT_WC_index == 1)
|
||||
{
|
||||
return NV_PAT_MODE_KERNEL;
|
||||
}
|
||||
else if (PAT_WC_index != 0xf)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: PAT configuration unsupported.\n");
|
||||
return NV_PAT_MODE_DISABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NV_ENABLE_BUILTIN_PAT_SUPPORT
|
||||
return NV_PAT_MODE_BUILTIN;
|
||||
#else
|
||||
return NV_PAT_MODE_DISABLED;
|
||||
#endif /* NV_ENABLE_BUILTIN_PAT_SUPPORT */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int nv_enable_pat_support(void)
|
||||
{
|
||||
if (nv_pat_mode != NV_PAT_MODE_DISABLED)
|
||||
return 1;
|
||||
|
||||
nv_pat_mode = nv_determine_pat_mode();
|
||||
|
||||
switch (nv_pat_mode)
|
||||
{
|
||||
case NV_PAT_MODE_DISABLED:
|
||||
/* avoid the PAT if unavailable/unusable */
|
||||
return 0;
|
||||
case NV_PAT_MODE_KERNEL:
|
||||
/* inherit the kernel's PAT layout */
|
||||
return 1;
|
||||
case NV_PAT_MODE_BUILTIN:
|
||||
/* use builtin code to modify the PAT layout */
|
||||
break;
|
||||
}
|
||||
|
||||
return nv_enable_builtin_pat_support();
|
||||
}
|
||||
|
||||
void nv_disable_pat_support(void)
|
||||
{
|
||||
if (nv_pat_mode != NV_PAT_MODE_BUILTIN)
|
||||
return;
|
||||
|
||||
nv_disable_builtin_pat_support();
|
||||
}
|
||||
|
||||
int nv_init_pat_support(nvidia_stack_t *sp)
|
||||
{
|
||||
NV_STATUS status;
|
||||
NvU32 data;
|
||||
int disable_pat = 0;
|
||||
int ret = 0;
|
||||
|
||||
status = rm_read_registry_dword(sp, NULL,
|
||||
NV_USE_PAGE_ATTRIBUTE_TABLE, &data);
|
||||
if ((status == NV_OK) && ((int)data != ~0))
|
||||
{
|
||||
disable_pat = (data == 0);
|
||||
}
|
||||
|
||||
if (!disable_pat)
|
||||
{
|
||||
nv_enable_pat_support();
|
||||
if (nv_pat_mode == NV_PAT_MODE_BUILTIN)
|
||||
{
|
||||
ret = nvidia_register_cpu_hotplug_notifier();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: builtin PAT support disabled.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv_teardown_pat_support(void)
|
||||
{
|
||||
if (nv_pat_mode == NV_PAT_MODE_BUILTIN)
|
||||
{
|
||||
nv_disable_pat_support();
|
||||
nvidia_unregister_cpu_hotplug_notifier();
|
||||
}
|
||||
}
|
||||
#endif /* defined(NV_ENABLE_PAT_SUPPORT) */
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NV_PAT_H_
|
||||
#define _NV_PAT_H_
|
||||
|
||||
#include "nv-linux.h"
|
||||
|
||||
|
||||
#if defined(NV_ENABLE_PAT_SUPPORT)
|
||||
extern int nv_init_pat_support(nvidia_stack_t *sp);
|
||||
extern void nv_teardown_pat_support(void);
|
||||
extern int nv_enable_pat_support(void);
|
||||
extern void nv_disable_pat_support(void);
|
||||
#else
|
||||
static inline int nv_init_pat_support(nvidia_stack_t *sp)
|
||||
{
|
||||
(void)sp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void nv_teardown_pat_support(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int nv_enable_pat_support(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void nv_disable_pat_support(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NV_PAT_H_ */
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "nv-pci-table.h"
|
||||
|
||||
/* Devices supported by RM */
|
||||
struct pci_device_id nv_pci_table[] = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NVIDIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = (PCI_CLASS_DISPLAY_VGA << 8),
|
||||
.class_mask = ~0
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NVIDIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = (PCI_CLASS_DISPLAY_3D << 8),
|
||||
.class_mask = ~0
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
/* Devices supported by all drivers in nvidia.ko */
|
||||
struct pci_device_id nv_module_device_table[] = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NVIDIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = (PCI_CLASS_DISPLAY_VGA << 8),
|
||||
.class_mask = ~0
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NVIDIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = (PCI_CLASS_DISPLAY_3D << 8),
|
||||
.class_mask = ~0
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_NVIDIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = (PCI_CLASS_BRIDGE_OTHER << 8),
|
||||
.class_mask = ~0
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, nv_module_device_table);
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NV_PCI_TABLE_H_
|
||||
#define _NV_PCI_TABLE_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
extern struct pci_device_id nv_pci_table[];
|
||||
|
||||
#endif /* _NV_PCI_TABLE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,932 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2006-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//
|
||||
// This file holds Unix-specific NVIDIA driver options
|
||||
//
|
||||
|
||||
#ifndef _RM_REG_H_
|
||||
#define _RM_REG_H_
|
||||
|
||||
#include "nvtypes.h"
|
||||
#include "nv-firmware-registry.h"
|
||||
|
||||
/*
|
||||
* use NV_REG_STRING to stringify a registry key when using that registry key
|
||||
*/
|
||||
|
||||
#define __NV_REG_STRING(regkey) #regkey
|
||||
#define NV_REG_STRING(regkey) __NV_REG_STRING(regkey)
|
||||
|
||||
/*
|
||||
* use NV_DEFINE_REG_ENTRY and NV_DEFINE_PARAMS_TABLE_ENTRY to simplify definition
|
||||
* of registry keys in the kernel module source code.
|
||||
*/
|
||||
|
||||
#define __NV_REG_VAR(regkey) NVreg_##regkey
|
||||
|
||||
#if defined(NV_MODULE_PARAMETER)
|
||||
#define NV_DEFINE_REG_ENTRY(regkey, default_value) \
|
||||
static NvU32 __NV_REG_VAR(regkey) = (default_value); \
|
||||
NV_MODULE_PARAMETER(__NV_REG_VAR(regkey))
|
||||
#define NV_DEFINE_REG_ENTRY_GLOBAL(regkey, default_value) \
|
||||
NvU32 __NV_REG_VAR(regkey) = (default_value); \
|
||||
NV_MODULE_PARAMETER(__NV_REG_VAR(regkey))
|
||||
#else
|
||||
#define NV_DEFINE_REG_ENTRY(regkey, default_value) \
|
||||
static NvU32 __NV_REG_VAR(regkey) = (default_value)
|
||||
#define NV_DEFINE_REG_ENTRY_GLOBAL(regkey, default_value) \
|
||||
NvU32 __NV_REG_VAR(regkey) = (default_value)
|
||||
#endif
|
||||
|
||||
#if defined(NV_MODULE_STRING_PARAMETER)
|
||||
#define NV_DEFINE_REG_STRING_ENTRY(regkey, default_value) \
|
||||
char *__NV_REG_VAR(regkey) = (default_value); \
|
||||
NV_MODULE_STRING_PARAMETER(__NV_REG_VAR(regkey))
|
||||
#else
|
||||
#define NV_DEFINE_REG_STRING_ENTRY(regkey, default_value) \
|
||||
char *__NV_REG_VAR(regkey) = (default_value)
|
||||
#endif
|
||||
|
||||
#define NV_DEFINE_PARAMS_TABLE_ENTRY(regkey) \
|
||||
{ NV_REG_STRING(regkey), &__NV_REG_VAR(regkey) }
|
||||
|
||||
/*
|
||||
* Like NV_DEFINE_PARMS_TABLE_ENTRY, but allows a mismatch between the name of
|
||||
* the regkey and the name of the module parameter. When using this macro, the
|
||||
* name of the parameter is passed to the extra "parameter" argument, and it is
|
||||
* this name that must be used in the NV_DEFINE_REG_ENTRY() macro.
|
||||
*/
|
||||
|
||||
#define NV_DEFINE_PARAMS_TABLE_ENTRY_CUSTOM_NAME(regkey, parameter) \
|
||||
{ NV_REG_STRING(regkey), &__NV_REG_VAR(parameter)}
|
||||
|
||||
/*
|
||||
*----------------- registry key definitions--------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Option: ModifyDeviceFiles
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will verify the validity
|
||||
* of the NVIDIA device files in /dev and attempt to dynamically modify
|
||||
* and/or (re-)create them, if necessary. If you don't wish for the NVIDIA
|
||||
* driver to touch the device files, you can use this registry key.
|
||||
*
|
||||
* This module parameter is only honored by the NVIDIA GPU driver and NVIDIA
|
||||
* capability driver. Furthermore, the NVIDIA capability driver provides
|
||||
* modifiable /proc file entry (DeviceFileModify=0/1) to alter the behavior of
|
||||
* this module parameter per device file.
|
||||
*
|
||||
* Possible Values:
|
||||
* 0 = disable dynamic device file management
|
||||
* 1 = enable dynamic device file management (default)
|
||||
*/
|
||||
|
||||
#define __NV_MODIFY_DEVICE_FILES ModifyDeviceFiles
|
||||
#define NV_REG_MODIFY_DEVICE_FILES NV_REG_STRING(__NV_MODIFY_DEVICE_FILES)
|
||||
|
||||
/*
|
||||
* Option: DeviceFileUID
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This registry key specifies the UID assigned to the NVIDIA device files
|
||||
* created and/or modified by the NVIDIA driver when dynamic device file
|
||||
* management is enabled.
|
||||
*
|
||||
* This module parameter is only honored by the NVIDIA GPU driver.
|
||||
*
|
||||
* The default UID is 0 ('root').
|
||||
*/
|
||||
|
||||
#define __NV_DEVICE_FILE_UID DeviceFileUID
|
||||
#define NV_REG_DEVICE_FILE_UID NV_REG_STRING(__NV_DEVICE_FILE_UID)
|
||||
|
||||
/*
|
||||
* Option: DeviceFileGID
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This registry key specifies the GID assigned to the NVIDIA device files
|
||||
* created and/or modified by the NVIDIA driver when dynamic device file
|
||||
* management is enabled.
|
||||
*
|
||||
* This module parameter is only honored by the NVIDIA GPU driver.
|
||||
*
|
||||
* The default GID is 0 ('root').
|
||||
*/
|
||||
|
||||
#define __NV_DEVICE_FILE_GID DeviceFileGID
|
||||
#define NV_REG_DEVICE_FILE_GID NV_REG_STRING(__NV_DEVICE_FILE_GID)
|
||||
|
||||
/*
|
||||
* Option: DeviceFileMode
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This registry key specifies the device file mode assigned to the NVIDIA
|
||||
* device files created and/or modified by the NVIDIA driver when dynamic
|
||||
* device file management is enabled.
|
||||
*
|
||||
* This module parameter is only honored by the NVIDIA GPU driver.
|
||||
*
|
||||
* The default mode is 0666 (octal, rw-rw-rw-).
|
||||
*/
|
||||
|
||||
#define __NV_DEVICE_FILE_MODE DeviceFileMode
|
||||
#define NV_REG_DEVICE_FILE_MODE NV_REG_STRING(__NV_DEVICE_FILE_MODE)
|
||||
|
||||
/*
|
||||
* Option: ResmanDebugLevel
|
||||
*
|
||||
* Default value: ~0
|
||||
*/
|
||||
|
||||
#define __NV_RESMAN_DEBUG_LEVEL ResmanDebugLevel
|
||||
#define NV_REG_RESMAN_DEBUG_LEVEL NV_REG_STRING(__NV_RESMAN_DEBUG_LEVEL)
|
||||
|
||||
/*
|
||||
* Option: RmLogonRC
|
||||
*
|
||||
* Default value: 1
|
||||
*/
|
||||
|
||||
#define __NV_RM_LOGON_RC RmLogonRC
|
||||
#define NV_REG_RM_LOGON_RC NV_REG_STRING(__NV_RM_LOGON_RC)
|
||||
|
||||
/*
|
||||
* Option: InitializeSystemMemoryAllocations
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* The NVIDIA Linux driver normally clears system memory it allocates
|
||||
* for use with GPUs or within the driver stack. This is to ensure
|
||||
* that potentially sensitive data is not rendered accessible by
|
||||
* arbitrary user applications.
|
||||
*
|
||||
* Owners of single-user systems or similar trusted configurations may
|
||||
* choose to disable the aforementioned clears using this option and
|
||||
* potentially improve performance.
|
||||
*
|
||||
* Possible values:
|
||||
*
|
||||
* 1 = zero out system memory allocations (default)
|
||||
* 0 = do not perform memory clears
|
||||
*/
|
||||
|
||||
#define __NV_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS \
|
||||
InitializeSystemMemoryAllocations
|
||||
#define NV_REG_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS \
|
||||
NV_REG_STRING(__NV_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS)
|
||||
|
||||
/*
|
||||
* Option: RegistryDwords
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This option accepts a semicolon-separated list of key=value pairs. Each
|
||||
* key name is checked against the table of static options; if a match is
|
||||
* found, the static option value is overridden, but invalid options remain
|
||||
* invalid. Pairs that do not match an entry in the static option table
|
||||
* are passed on to the RM directly.
|
||||
*
|
||||
* Format:
|
||||
*
|
||||
* NVreg_RegistryDwords="<key=value>;<key=value>;..."
|
||||
*/
|
||||
|
||||
#define __NV_REGISTRY_DWORDS RegistryDwords
|
||||
#define NV_REG_REGISTRY_DWORDS NV_REG_STRING(__NV_REGISTRY_DWORDS)
|
||||
|
||||
/*
|
||||
* Option: RegistryDwordsPerDevice
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This option allows to specify registry keys per GPU device. It helps to
|
||||
* control registry at GPU level of granularity. It accepts a semicolon
|
||||
* separated list of key=value pairs. The first key value pair MUST be
|
||||
* "pci=DDDD:BB:DD.F;" where DDDD is Domain, BB is Bus Id, DD is device slot
|
||||
* number and F is the Function. This PCI BDF is used to identify which GPU to
|
||||
* assign the registry keys that follows next.
|
||||
* If a GPU corresponding to the value specified in "pci=DDDD:BB:DD.F;" is NOT
|
||||
* found, then all the registry keys that follows are skipped, until we find next
|
||||
* valid pci identified "pci=DDDD:BB:DD.F;". Following are the valid formats for
|
||||
* the value of the "pci" string:
|
||||
* 1) bus:slot : Domain and function defaults to 0.
|
||||
* 2) domain:bus:slot : Function defaults to 0.
|
||||
* 3) domain:bus:slot.func : Complete PCI dev id string.
|
||||
*
|
||||
* For each of the registry keys that follows, key name is checked against the
|
||||
* table of static options; if a match is found, the static option value is
|
||||
* overridden, but invalid options remain invalid. Pairs that do not match an
|
||||
* entry in the static option table are passed on to the RM directly.
|
||||
*
|
||||
* Format:
|
||||
*
|
||||
* NVreg_RegistryDwordsPerDevice="pci=DDDD:BB:DD.F;<key=value>;<key=value>;..; \
|
||||
* pci=DDDD:BB:DD.F;<key=value>;..;"
|
||||
*/
|
||||
|
||||
#define __NV_REGISTRY_DWORDS_PER_DEVICE RegistryDwordsPerDevice
|
||||
#define NV_REG_REGISTRY_DWORDS_PER_DEVICE NV_REG_STRING(__NV_REGISTRY_DWORDS_PER_DEVICE)
|
||||
|
||||
#define __NV_RM_MSG RmMsg
|
||||
#define NV_RM_MSG NV_REG_STRING(__NV_RM_MSG)
|
||||
|
||||
/*
|
||||
* Option: UsePageAttributeTable
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Enable/disable use of the page attribute table (PAT) available in
|
||||
* modern x86/x86-64 processors to set the effective memory type of memory
|
||||
* mappings to write-combining (WC).
|
||||
*
|
||||
* If enabled, an x86 processor with PAT support is present and the host
|
||||
* system's Linux kernel did not configure one of the PAT entries to
|
||||
* indicate the WC memory type, the driver will change the second entry in
|
||||
* the PAT from its default (write-through (WT)) to WC at module load
|
||||
* time. If the kernel did update one of the PAT entries, the driver will
|
||||
* not modify the PAT.
|
||||
*
|
||||
* In both cases, the driver will honor attempts to map memory with the WC
|
||||
* memory type by selecting the appropriate PAT entry using the correct
|
||||
* set of PTE flags.
|
||||
*
|
||||
* Possible values:
|
||||
*
|
||||
* ~0 = use the NVIDIA driver's default logic (default)
|
||||
* 1 = enable use of the PAT for WC mappings.
|
||||
* 0 = disable use of the PAT for WC mappings.
|
||||
*/
|
||||
|
||||
#define __NV_USE_PAGE_ATTRIBUTE_TABLE UsePageAttributeTable
|
||||
#define NV_USE_PAGE_ATTRIBUTE_TABLE NV_REG_STRING(__NV_USE_PAGE_ATTRIBUTE_TABLE)
|
||||
|
||||
/*
|
||||
* Option: EnableMSI
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled and the host kernel supports the MSI feature,
|
||||
* the NVIDIA driver will enable the PCI-E MSI capability of GPUs with the
|
||||
* support for this feature instead of using PCI-E wired interrupt.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0 = disable MSI interrupt
|
||||
* 1 = enable MSI interrupt (default)
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NV_ENABLE_MSI EnableMSI
|
||||
#define NV_REG_ENABLE_MSI NV_REG_STRING(__NV_ENABLE_MSI)
|
||||
|
||||
/*
|
||||
* Option: EnablePCIeGen3
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Due to interoperability problems seen with Kepler PCIe Gen3 capable GPUs
|
||||
* when configured on SandyBridge E desktop platforms, NVIDIA feels that
|
||||
* delivering a reliable, high-quality experience is not currently possible in
|
||||
* PCIe Gen3 mode on all PCIe Gen3 platforms. Therefore, Quadro, Tesla and
|
||||
* NVS Kepler products operate in PCIe Gen2 mode by default. You may use this
|
||||
* option to enable PCIe Gen3 support.
|
||||
*
|
||||
* This is completely unsupported!
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: disable PCIe Gen3 support (default)
|
||||
* 1: enable PCIe Gen3 support
|
||||
*/
|
||||
|
||||
#define __NV_ENABLE_PCIE_GEN3 EnablePCIeGen3
|
||||
#define NV_REG_ENABLE_PCIE_GEN3 NV_REG_STRING(__NV_ENABLE_PCIE_GEN3)
|
||||
|
||||
/*
|
||||
* Option: MemoryPoolSize
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When set to a non-zero value, this option specifies the size of the
|
||||
* memory pool, given as a multiple of 1 GB, created on VMware ESXi to
|
||||
* satisfy any system memory allocations requested by the NVIDIA kernel
|
||||
* module.
|
||||
*/
|
||||
|
||||
#define __NV_MEMORY_POOL_SIZE MemoryPoolSize
|
||||
#define NV_REG_MEMORY_POOL_SIZE NV_REG_STRING(__NV_MEMORY_POOL_SIZE)
|
||||
|
||||
/*
|
||||
* Option: KMallocHeapMaxSize
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When set to a non-zero value, this option specifies the maximum size of the
|
||||
* heap memory space reserved for kmalloc operations. Given as a
|
||||
* multiple of 1 MB created on VMware ESXi to satisfy any system memory
|
||||
* allocations requested by the NVIDIA kernel module.
|
||||
*/
|
||||
|
||||
#define __NV_KMALLOC_HEAP_MAX_SIZE KMallocHeapMaxSize
|
||||
#define NV_KMALLOC_HEAP_MAX_SIZE NV_REG_STRING(__NV_KMALLOC_HEAP_MAX_SIZE)
|
||||
|
||||
/*
|
||||
* Option: VMallocHeapMaxSize
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When set to a non-zero value, this option specifies the maximum size of the
|
||||
* heap memory space reserved for vmalloc operations. Given as a
|
||||
* multiple of 1 MB created on VMware ESXi to satisfy any system memory
|
||||
* allocations requested by the NVIDIA kernel module.
|
||||
*/
|
||||
|
||||
#define __NV_VMALLOC_HEAP_MAX_SIZE VMallocHeapMaxSize
|
||||
#define NV_VMALLOC_HEAP_MAX_SIZE NV_REG_STRING(__NV_VMALLOC_HEAP_MAX_SIZE)
|
||||
|
||||
/*
|
||||
* Option: IgnoreMMIOCheck
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA kernel module will ignore
|
||||
* MMIO limit check during device probe on VMWare ESXi kernel. This is
|
||||
* typically necessary when VMware ESXi MMIO limit differs between any
|
||||
* base version and its updates. Customer using updates can set regkey
|
||||
* to avoid probe failure.
|
||||
*/
|
||||
|
||||
#define __NV_IGNORE_MMIO_CHECK IgnoreMMIOCheck
|
||||
#define NV_REG_IGNORE_MMIO_CHECK NV_REG_STRING(__NV_IGNORE_MMIO_CHECK)
|
||||
|
||||
/*
|
||||
* Option: TCEBypassMode
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA kernel module will attempt to setup
|
||||
* all GPUs in "TCE bypass mode", in which DMA mappings of system memory bypass
|
||||
* the IOMMU/TCE remapping hardware on IBM POWER systems. This is typically
|
||||
* necessary for CUDA applications in which large system memory mappings may
|
||||
* exceed the default TCE remapping capacity when operated in non-bypass mode.
|
||||
*
|
||||
* This option has no effect on non-POWER platforms.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: system default TCE mode on all GPUs
|
||||
* 1: enable TCE bypass mode on all GPUs
|
||||
* 2: disable TCE bypass mode on all GPUs
|
||||
*/
|
||||
#define __NV_TCE_BYPASS_MODE TCEBypassMode
|
||||
#define NV_REG_TCE_BYPASS_MODE NV_REG_STRING(__NV_TCE_BYPASS_MODE)
|
||||
|
||||
#define NV_TCE_BYPASS_MODE_DEFAULT 0
|
||||
#define NV_TCE_BYPASS_MODE_ENABLE 1
|
||||
#define NV_TCE_BYPASS_MODE_DISABLE 2
|
||||
|
||||
/*
|
||||
* Option: pci
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* On Unix platforms, per GPU based registry key can be specified as:
|
||||
* NVreg_RegistryDwordsPerDevice="pci=DDDD:BB:DD.F,<per-gpu registry keys>".
|
||||
* where DDDD:BB:DD.F refers to Domain:Bus:Device.Function.
|
||||
* We need this key "pci" to identify what follows next is a PCI BDF identifier,
|
||||
* for which the registry keys are to be applied.
|
||||
*
|
||||
* This define is not used on non-UNIX platforms.
|
||||
*
|
||||
* Possible Formats for value:
|
||||
*
|
||||
* 1) bus:slot : Domain and function defaults to 0.
|
||||
* 2) domain:bus:slot : Function defaults to 0.
|
||||
* 3) domain:bus:slot.func : Complete PCI BDF identifier string.
|
||||
*/
|
||||
#define __NV_PCI_DEVICE_BDF pci
|
||||
#define NV_REG_PCI_DEVICE_BDF NV_REG_STRING(__NV_PCI_DEVICE_BDF)
|
||||
|
||||
/*
|
||||
* Option: EnableStreamMemOPs
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the CUDA driver will enable support for
|
||||
* CUDA Stream Memory Operations in user-mode applications, which are so
|
||||
* far required to be disabled by default due to limited support in
|
||||
* devtools.
|
||||
*
|
||||
* Note: this is treated as a hint. MemOPs may still be left disabled by CUDA
|
||||
* driver for other reasons.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0 = disable feature (default)
|
||||
* 1 = enable feature
|
||||
*/
|
||||
#define __NV_ENABLE_STREAM_MEMOPS EnableStreamMemOPs
|
||||
#define NV_REG_ENABLE_STREAM_MEMOPS NV_REG_STRING(__NV_ENABLE_STREAM_MEMOPS)
|
||||
|
||||
/*
|
||||
* Option: EnableUserNUMAManagement
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA kernel module will require the
|
||||
* user-mode NVIDIA Persistence daemon to manage the onlining and offlining
|
||||
* of its NUMA device memory.
|
||||
*
|
||||
* This option has no effect on platforms that do not support onlining
|
||||
* device memory to a NUMA node (this feature is only supported on certain
|
||||
* POWER9 systems).
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: disable user-mode NUMA management
|
||||
* 1: enable user-mode NUMA management (default)
|
||||
*/
|
||||
#define __NV_ENABLE_USER_NUMA_MANAGEMENT EnableUserNUMAManagement
|
||||
#define NV_REG_ENABLE_USER_NUMA_MANAGEMENT NV_REG_STRING(__NV_ENABLE_USER_NUMA_MANAGEMENT)
|
||||
|
||||
/*
|
||||
* Option: GpuBlacklist
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This option accepts a list of blacklisted GPUs, separated by commas, that
|
||||
* cannot be attached or used. Each blacklisted GPU is identified by a UUID in
|
||||
* the ASCII format with leading "GPU-". An exact match is required; no partial
|
||||
* UUIDs. This regkey is deprecated and will be removed in the future. Use
|
||||
* NV_REG_EXCLUDED_GPUS instead.
|
||||
*/
|
||||
#define __NV_GPU_BLACKLIST GpuBlacklist
|
||||
#define NV_REG_GPU_BLACKLIST NV_REG_STRING(__NV_GPU_BLACKLIST)
|
||||
|
||||
/*
|
||||
* Option: ExcludedGpus
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This option accepts a list of excluded GPUs, separated by commas, that
|
||||
* cannot be attached or used. Each excluded GPU is identified by a UUID in
|
||||
* the ASCII format with leading "GPU-". An exact match is required; no partial
|
||||
* UUIDs.
|
||||
*/
|
||||
#define __NV_EXCLUDED_GPUS ExcludedGpus
|
||||
#define NV_REG_EXCLUDED_GPUS NV_REG_STRING(__NV_EXCLUDED_GPUS)
|
||||
|
||||
/*
|
||||
* Option: NvLinkDisable
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA kernel module will not attempt to
|
||||
* initialize or train NVLink connections for any GPUs. System reboot is required
|
||||
* for changes to take affect.
|
||||
*
|
||||
* This option has no effect if no GPUs support NVLink.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: Do not disable NVLink (default)
|
||||
* 1: Disable NVLink
|
||||
*/
|
||||
#define __NV_NVLINK_DISABLE NvLinkDisable
|
||||
#define NV_REG_NVLINK_DISABLE NV_REG_STRING(__NV_NVLINK_DISABLE)
|
||||
|
||||
/*
|
||||
* Option: RestrictProfilingToAdminUsers
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA kernel module will prevent users
|
||||
* without administrative access (i.e., the CAP_SYS_ADMIN capability) from
|
||||
* using GPU performance counters.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: Do not restrict GPU counters (default)
|
||||
* 1: Restrict GPU counters to system administrators only
|
||||
*/
|
||||
|
||||
#define __NV_RM_PROFILING_ADMIN_ONLY RmProfilingAdminOnly
|
||||
#define __NV_RM_PROFILING_ADMIN_ONLY_PARAMETER RestrictProfilingToAdminUsers
|
||||
#define NV_REG_RM_PROFILING_ADMIN_ONLY NV_REG_STRING(__NV_RM_PROFILING_ADMIN_ONLY)
|
||||
|
||||
/*
|
||||
* Option: TemporaryFilePath
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When specified, this option changes the location in which the
|
||||
* NVIDIA kernel module will create unnamed temporary files (e.g. to
|
||||
* save the contents of video memory in). The indicated file must
|
||||
* be a directory. By default, temporary files are created in /tmp.
|
||||
*/
|
||||
#define __NV_TEMPORARY_FILE_PATH TemporaryFilePath
|
||||
#define NV_REG_TEMPORARY_FILE_PATH NV_REG_STRING(__NV_TEMPORARY_FILE_PATH)
|
||||
|
||||
/*
|
||||
* Option: PreserveVideoMemoryAllocations
|
||||
*
|
||||
* If enabled, this option prompts the NVIDIA kernel module to save and
|
||||
* restore all video memory allocations across system power management
|
||||
* cycles, i.e. suspend/resume and hibernate/restore. Otherwise,
|
||||
* only select allocations are preserved.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: Preserve only select video memory allocations (default)
|
||||
* 1: Preserve all video memory allocations
|
||||
*/
|
||||
#define __NV_PRESERVE_VIDEO_MEMORY_ALLOCATIONS PreserveVideoMemoryAllocations
|
||||
#define NV_REG_PRESERVE_VIDEO_MEMORY_ALLOCATIONS \
|
||||
NV_REG_STRING(__NV_PRESERVE_VIDEO_MEMORY_ALLOCATIONS)
|
||||
|
||||
/*
|
||||
* Option: EnableS0ixPowerManagement
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will use S0ix-based
|
||||
* power management for system suspend/resume, if both the platform and
|
||||
* the GPU support S0ix.
|
||||
*
|
||||
* During system suspend, if S0ix is enabled and
|
||||
* video memory usage is above the threshold configured by
|
||||
* 'S0ixPowerManagementVideoMemoryThreshold', video memory will be kept
|
||||
* in self-refresh mode while the rest of the GPU is powered down.
|
||||
*
|
||||
* Otherwise, the driver will copy video memory contents to system memory
|
||||
* and power off the video memory along with the GPU.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: Disable S0ix based power management (default)
|
||||
* 1: Enable S0ix based power management
|
||||
*/
|
||||
|
||||
#define __NV_ENABLE_S0IX_POWER_MANAGEMENT EnableS0ixPowerManagement
|
||||
#define NV_REG_ENABLE_S0IX_POWER_MANAGEMENT \
|
||||
NV_REG_STRING(__NV_ENABLE_S0IX_POWER_MANAGEMENT)
|
||||
|
||||
/*
|
||||
* Option: S0ixPowerManagementVideoMemoryThreshold
|
||||
*
|
||||
* This option controls the threshold that the NVIDIA driver will use during
|
||||
* S0ix-based system power management.
|
||||
*
|
||||
* When S0ix is enabled and the system is suspended, the driver will
|
||||
* compare the amount of video memory in use with this threshold,
|
||||
* to decide whether to keep video memory in self-refresh or copy video
|
||||
* memory content to system memory.
|
||||
*
|
||||
* See the 'EnableS0ixPowerManagement' option.
|
||||
*
|
||||
* Values are expressed in Megabytes (1048576 bytes).
|
||||
*
|
||||
* Default value for this option is 256MB.
|
||||
*
|
||||
*/
|
||||
#define __NV_S0IX_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD \
|
||||
S0ixPowerManagementVideoMemoryThreshold
|
||||
#define NV_REG_S0IX_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD \
|
||||
NV_REG_STRING(__NV_S0IX_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD)
|
||||
|
||||
/*
|
||||
* Option: DynamicPowerManagement
|
||||
*
|
||||
* This option controls how aggressively the NVIDIA kernel module will manage
|
||||
* GPU power through kernel interfaces.
|
||||
*
|
||||
* Possible Values:
|
||||
*
|
||||
* 0: Never allow the GPU to be powered down (default).
|
||||
* 1: Power down the GPU when it is not initialized.
|
||||
* 2: Power down the GPU after it has been inactive for some time.
|
||||
* 3: (Default) Power down the GPU after a period of inactivity (i.e.,
|
||||
* mode 2) on Ampere or later notebooks. Otherwise, do not power down
|
||||
* the GPU.
|
||||
*/
|
||||
#define __NV_DYNAMIC_POWER_MANAGEMENT DynamicPowerManagement
|
||||
#define NV_REG_DYNAMIC_POWER_MANAGEMENT \
|
||||
NV_REG_STRING(__NV_DYNAMIC_POWER_MANAGEMENT)
|
||||
|
||||
#define NV_REG_DYNAMIC_POWER_MANAGEMENT_NEVER 0
|
||||
#define NV_REG_DYNAMIC_POWER_MANAGEMENT_COARSE 1
|
||||
#define NV_REG_DYNAMIC_POWER_MANAGEMENT_FINE 2
|
||||
#define NV_REG_DYNAMIC_POWER_MANAGEMENT_DEFAULT 3
|
||||
|
||||
/*
|
||||
* Option: DynamicPowerManagementVideoMemoryThreshold
|
||||
*
|
||||
* This option controls the threshold that the NVIDIA driver will use
|
||||
* when selecting the dynamic power management scheme.
|
||||
*
|
||||
* When the driver detects that the GPU is idle, it will compare the amount
|
||||
* of video memory in use with this threshold.
|
||||
*
|
||||
* If the current video memory usage is less than the threshold, the
|
||||
* driver may preserve video memory contents in system memory and power off
|
||||
* the video memory along with the GPU itself, if supported. Otherwise,
|
||||
* the video memory will be kept in self-refresh mode while powering down
|
||||
* the rest of the GPU, if supported.
|
||||
*
|
||||
* Values are expressed in Megabytes (1048576 bytes).
|
||||
*
|
||||
* If the requested value is greater than 200MB (the default), then it
|
||||
* will be capped to 200MB.
|
||||
*/
|
||||
#define __NV_DYNAMIC_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD \
|
||||
DynamicPowerManagementVideoMemoryThreshold
|
||||
#define NV_REG_DYNAMIC_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD \
|
||||
NV_REG_STRING(__NV_DYNAMIC_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD)
|
||||
|
||||
/*
|
||||
* Option: RegisterPCIDriver
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will register with
|
||||
* PCI subsystem.
|
||||
*
|
||||
* Possible values:
|
||||
*
|
||||
* 1 - register as PCI driver (default)
|
||||
* 0 - do not register as PCI driver
|
||||
*/
|
||||
|
||||
#define __NV_REGISTER_PCI_DRIVER RegisterPCIDriver
|
||||
#define NV_REG_REGISTER_PCI_DRIVER NV_REG_STRING(__NV_REGISTER_PCI_DRIVER)
|
||||
|
||||
/*
|
||||
* Option: EnablePCIERelaxedOrderingMode
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the registry key RmSetPCIERelaxedOrdering will
|
||||
* be set to NV_REG_STR_RM_SET_PCIE_TLP_RELAXED_ORDERING_FORCE_ENABLE, causing
|
||||
* every device to set the relaxed ordering bit to 1 in all outbound MWr
|
||||
* transaction-layer packets. This is equivalent to setting the regkey to
|
||||
* FORCE_ENABLE as a non-per-device registry key.
|
||||
*
|
||||
* Possible values:
|
||||
* 0 - Do not enable PCIe TLP relaxed ordering bit-setting (default)
|
||||
* 1 - Enable PCIe TLP relaxed ordering bit-setting
|
||||
*/
|
||||
#define __NV_ENABLE_PCIE_RELAXED_ORDERING_MODE EnablePCIERelaxedOrderingMode
|
||||
#define NV_REG_ENABLE_PCIE_RELAXED_ORDERING_MODE \
|
||||
NV_REG_STRING(__NV_ENABLE_PCIE_RELAXED_ORDERING_MODE)
|
||||
|
||||
/*
|
||||
* Option: EnableResizableBar
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will attempt to resize
|
||||
* BAR1 to match framebuffer size, or the next largest available size on
|
||||
* supported machines. This is currently only implemented for Linux.
|
||||
*
|
||||
* Possible values:
|
||||
* 0 - Do not enable PCI BAR resizing
|
||||
* 1 - Enable PCI BAR resizing
|
||||
*/
|
||||
#define __NV_ENABLE_RESIZABLE_BAR EnableResizableBar
|
||||
#define NV_REG_ENABLE_RESIZABLE_BAR NV_REG_STRING(__NV_ENABLE_RESIZABLE_BAR)
|
||||
|
||||
/*
|
||||
* Option: EnableGpuFirmware
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will enable use of GPU
|
||||
* firmware.
|
||||
*
|
||||
* If this key is set globally to the system, the driver may still attempt
|
||||
* to apply some policies to maintain uniform firmware modes across all
|
||||
* GPUS. This may result in the driver failing initialization on some GPUs
|
||||
* to maintain such a policy.
|
||||
*
|
||||
* If this key is set using NVreg_RegistryDwordsPerDevice, then the driver
|
||||
* will attempt to honor whatever configuration is specified without applying
|
||||
* additional policies. This may also result in failed GPU initialzations if
|
||||
* the configuration is not possible (for example if the firmware is missing
|
||||
* from the filesystem, or the GPU is not capable).
|
||||
*
|
||||
* NOTE: More details for this regkey can be found in nv-firmware-registry.h
|
||||
*/
|
||||
#define __NV_ENABLE_GPU_FIRMWARE EnableGpuFirmware
|
||||
#define NV_REG_ENABLE_GPU_FIRMWARE NV_REG_STRING(__NV_ENABLE_GPU_FIRMWARE)
|
||||
|
||||
/*
|
||||
* Option: EnableGpuFirmwareLogs
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will send GPU firmware logs
|
||||
* to the system log, when possible.
|
||||
*
|
||||
* NOTE: More details for this regkey can be found in nv-firmware-registry.h
|
||||
*/
|
||||
#define __NV_ENABLE_GPU_FIRMWARE_LOGS EnableGpuFirmwareLogs
|
||||
#define NV_REG_ENABLE_GPU_FIRMWARE_LOGS NV_REG_STRING(__NV_ENABLE_GPU_FIRMWARE_LOGS)
|
||||
|
||||
/*
|
||||
* Option: EnableDbgBreakpoint
|
||||
*
|
||||
* When this option is set to a non-zero value, and the kernel is configured
|
||||
* appropriately, assertions within resman will trigger a CPU breakpoint (e.g.,
|
||||
* INT3 on x86_64), assumed to be caught by an attached debugger.
|
||||
*
|
||||
* When this option is set to the value zero (the default), assertions within
|
||||
* resman will print to the system log, but no CPU breakpoint will be triggered.
|
||||
*/
|
||||
#define __NV_ENABLE_DBG_BREAKPOINT EnableDbgBreakpoint
|
||||
|
||||
|
||||
/*
|
||||
* Option: OpenRmEnableUnsupportedGpus
|
||||
*
|
||||
* Open nvidia.ko support for features beyond what is used on Data Center GPUs
|
||||
* is still fairly immature, so for now require users to opt into use of open
|
||||
* nvidia.ko with a special registry key, if not on a Data Center GPU.
|
||||
*/
|
||||
|
||||
#define __NV_OPENRM_ENABLE_UNSUPPORTED_GPUS OpenRmEnableUnsupportedGpus
|
||||
#define NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS NV_REG_STRING(__NV_OPENRM_ENABLE_UNSUPPORTED_GPUS)
|
||||
#define NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_DISABLE 0x00000000
|
||||
#define NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_ENABLE 0x00000001
|
||||
#define NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_DEFAULT NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_DISABLE
|
||||
|
||||
/*
|
||||
* Option: NVreg_DmaRemapPeerMmio
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* When this option is enabled, the NVIDIA driver will use device driver
|
||||
* APIs provided by the Linux kernel for DMA-remapping part of a device's
|
||||
* MMIO region to another device, creating e.g., IOMMU mappings as necessary.
|
||||
* When this option is disabled, the NVIDIA driver will instead only apply a
|
||||
* fixed offset, which may be zero, to CPU physical addresses to produce the
|
||||
* DMA address for the peer's MMIO region, and no IOMMU mappings will be
|
||||
* created.
|
||||
*
|
||||
* This option only affects peer MMIO DMA mappings, and not system memory
|
||||
* mappings.
|
||||
*
|
||||
* Possible Values:
|
||||
* 0 = disable dynamic DMA remapping of peer MMIO regions
|
||||
* 1 = enable dynamic DMA remapping of peer MMIO regions (default)
|
||||
*/
|
||||
#define __NV_DMA_REMAP_PEER_MMIO DmaRemapPeerMmio
|
||||
#define NV_DMA_REMAP_PEER_MMIO NV_REG_STRING(__NV_DMA_REMAP_PEER_MMIO)
|
||||
#define NV_DMA_REMAP_PEER_MMIO_DISABLE 0x00000000
|
||||
#define NV_DMA_REMAP_PEER_MMIO_ENABLE 0x00000001
|
||||
|
||||
/*
|
||||
* Option: NVreg_RmNvlinkBandwidth
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* This option allows user to reduce the NVLINK P2P bandwidth to save power.
|
||||
* The option is in the string format.
|
||||
*
|
||||
* Possible string values:
|
||||
* OFF: 0% bandwidth
|
||||
* MIN: 15%-25% bandwidth depending on the system's NVLink topology
|
||||
* HALF: 50% bandwidth
|
||||
* 3QUARTER: 75% bandwidth
|
||||
* FULL: 100% bandwidth (default)
|
||||
*
|
||||
* This option is only for Hopper+ GPU with NVLINK version 4.0.
|
||||
*/
|
||||
#define __NV_RM_NVLINK_BW RmNvlinkBandwidth
|
||||
#define NV_RM_NVLINK_BW NV_REG_STRING(__NV_RM_NVLINK_BW)
|
||||
|
||||
#if defined(NV_DEFINE_REGISTRY_KEY_TABLE)
|
||||
|
||||
/*
|
||||
*---------registry key parameter declarations--------------
|
||||
*/
|
||||
|
||||
NV_DEFINE_REG_ENTRY(__NV_RESMAN_DEBUG_LEVEL, ~0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_RM_LOGON_RC, 1);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_MODIFY_DEVICE_FILES, 1);
|
||||
NV_DEFINE_REG_ENTRY(__NV_DEVICE_FILE_UID, 0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_DEVICE_FILE_GID, 0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_DEVICE_FILE_MODE, 0666);
|
||||
NV_DEFINE_REG_ENTRY(__NV_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS, 1);
|
||||
NV_DEFINE_REG_ENTRY(__NV_USE_PAGE_ATTRIBUTE_TABLE, ~0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_ENABLE_PCIE_GEN3, 0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_ENABLE_MSI, 1);
|
||||
NV_DEFINE_REG_ENTRY(__NV_TCE_BYPASS_MODE, NV_TCE_BYPASS_MODE_DEFAULT);
|
||||
NV_DEFINE_REG_ENTRY(__NV_ENABLE_STREAM_MEMOPS, 0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_RM_PROFILING_ADMIN_ONLY_PARAMETER, 1);
|
||||
NV_DEFINE_REG_ENTRY(__NV_PRESERVE_VIDEO_MEMORY_ALLOCATIONS, 0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_ENABLE_S0IX_POWER_MANAGEMENT, 0);
|
||||
NV_DEFINE_REG_ENTRY(__NV_S0IX_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD, 256);
|
||||
NV_DEFINE_REG_ENTRY(__NV_DYNAMIC_POWER_MANAGEMENT, 3);
|
||||
NV_DEFINE_REG_ENTRY(__NV_DYNAMIC_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD, 200);
|
||||
NV_DEFINE_REG_ENTRY(__NV_ENABLE_GPU_FIRMWARE, NV_REG_ENABLE_GPU_FIRMWARE_DEFAULT_VALUE);
|
||||
NV_DEFINE_REG_ENTRY(__NV_ENABLE_GPU_FIRMWARE_LOGS, NV_REG_ENABLE_GPU_FIRMWARE_LOGS_ENABLE_ON_DEBUG);
|
||||
NV_DEFINE_REG_ENTRY(__NV_OPENRM_ENABLE_UNSUPPORTED_GPUS, NV_REG_OPENRM_ENABLE_UNSUPPORTED_GPUS_DEFAULT);
|
||||
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_ENABLE_USER_NUMA_MANAGEMENT, 1);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_MEMORY_POOL_SIZE, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_KMALLOC_HEAP_MAX_SIZE, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_VMALLOC_HEAP_MAX_SIZE, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_IGNORE_MMIO_CHECK, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_NVLINK_DISABLE, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_ENABLE_PCIE_RELAXED_ORDERING_MODE, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_REGISTER_PCI_DRIVER, 1);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_ENABLE_RESIZABLE_BAR, 0);
|
||||
NV_DEFINE_REG_ENTRY_GLOBAL(__NV_ENABLE_DBG_BREAKPOINT, 0);
|
||||
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_REGISTRY_DWORDS, NULL);
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_REGISTRY_DWORDS_PER_DEVICE, NULL);
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_RM_MSG, NULL);
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_GPU_BLACKLIST, NULL);
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_TEMPORARY_FILE_PATH, NULL);
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_EXCLUDED_GPUS, NULL);
|
||||
NV_DEFINE_REG_ENTRY(__NV_DMA_REMAP_PEER_MMIO, NV_DMA_REMAP_PEER_MMIO_ENABLE);
|
||||
NV_DEFINE_REG_STRING_ENTRY(__NV_RM_NVLINK_BW, NULL);
|
||||
|
||||
/*
|
||||
*----------------registry database definition----------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* You can enable any of the registry options disabled by default by
|
||||
* editing their respective entries in the table below. The last field
|
||||
* determines if the option is considered valid - in order for the
|
||||
* changes to take effect, you need to recompile and reload the NVIDIA
|
||||
* kernel module.
|
||||
*/
|
||||
nv_parm_t nv_parms[] = {
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_RESMAN_DEBUG_LEVEL),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_RM_LOGON_RC),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_MODIFY_DEVICE_FILES),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DEVICE_FILE_UID),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DEVICE_FILE_GID),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DEVICE_FILE_MODE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_INITIALIZE_SYSTEM_MEMORY_ALLOCATIONS),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_USE_PAGE_ATTRIBUTE_TABLE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_MSI),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_PCIE_GEN3),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_MEMORY_POOL_SIZE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_KMALLOC_HEAP_MAX_SIZE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_VMALLOC_HEAP_MAX_SIZE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_IGNORE_MMIO_CHECK),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_TCE_BYPASS_MODE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_STREAM_MEMOPS),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_USER_NUMA_MANAGEMENT),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_NVLINK_DISABLE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY_CUSTOM_NAME(__NV_RM_PROFILING_ADMIN_ONLY,
|
||||
__NV_RM_PROFILING_ADMIN_ONLY_PARAMETER),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_PRESERVE_VIDEO_MEMORY_ALLOCATIONS),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_S0IX_POWER_MANAGEMENT),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_S0IX_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DYNAMIC_POWER_MANAGEMENT),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DYNAMIC_POWER_MANAGEMENT_VIDEO_MEMORY_THRESHOLD),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_REGISTER_PCI_DRIVER),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_PCIE_RELAXED_ORDERING_MODE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_RESIZABLE_BAR),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_GPU_FIRMWARE),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_GPU_FIRMWARE_LOGS),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_ENABLE_DBG_BREAKPOINT),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_OPENRM_ENABLE_UNSUPPORTED_GPUS),
|
||||
NV_DEFINE_PARAMS_TABLE_ENTRY(__NV_DMA_REMAP_PEER_MMIO),
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#elif defined(NVRM)
|
||||
|
||||
extern nv_parm_t nv_parms[];
|
||||
|
||||
#endif /* NV_DEFINE_REGISTRY_KEY_TABLE */
|
||||
|
||||
#endif /* _RM_REG_H_ */
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "nv-linux.h"
|
||||
#include "os-interface.h"
|
||||
|
||||
#include "nv-report-err.h"
|
||||
|
||||
nv_report_error_cb_t nv_error_cb_handle = NULL;
|
||||
|
||||
int nv_register_error_cb(nv_report_error_cb_t report_error_cb)
|
||||
{
|
||||
if (report_error_cb == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (nv_error_cb_handle != NULL)
|
||||
return -EBUSY;
|
||||
|
||||
nv_error_cb_handle = report_error_cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(nv_register_error_cb);
|
||||
|
||||
int nv_unregister_error_cb(void)
|
||||
{
|
||||
if (nv_error_cb_handle == NULL)
|
||||
return -EPERM;
|
||||
|
||||
nv_error_cb_handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(nv_unregister_error_cb);
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
void nv_report_error(
|
||||
struct pci_dev *dev,
|
||||
NvU32 error_number,
|
||||
const char *format,
|
||||
va_list ap
|
||||
)
|
||||
{
|
||||
va_list ap_copy;
|
||||
char *buffer;
|
||||
int length = 0;
|
||||
int status = NV_OK;
|
||||
|
||||
if (nv_error_cb_handle != NULL)
|
||||
{
|
||||
va_copy(ap_copy, ap);
|
||||
length = vsnprintf(NULL, 0, format, ap);
|
||||
va_end(ap_copy);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
status = os_alloc_mem((void *)&buffer, (length + 1)*sizeof(char));
|
||||
|
||||
if (status == NV_OK)
|
||||
{
|
||||
vsnprintf(buffer, length, format, ap);
|
||||
nv_error_cb_handle(dev, error_number, buffer, length + 1);
|
||||
os_free_mem(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NV_REPORT_ERR_H_
|
||||
#define _NV_REPORT_ERR_H_
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Callback definition for obtaining XID error string and data.
|
||||
*
|
||||
* @param[in] pci_dev *
|
||||
* Structure describring GPU PCI device.
|
||||
* @param[in] uint32_t
|
||||
* XID number
|
||||
* @param[in] char *
|
||||
* Error string with HWERR info.
|
||||
* @param[in] int
|
||||
* Length of error string.
|
||||
*/
|
||||
typedef void (*nv_report_error_cb_t)(struct pci_dev *, uint32_t, char *, int);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Register callback function to obtain XID error string and data.
|
||||
*
|
||||
* @param[in] report_error_cb
|
||||
* A function pointer to recieve callback.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EINVAL callback handle is NULL.
|
||||
* -EBUSY callback handle is already registered.
|
||||
*/
|
||||
int nv_register_error_cb(nv_report_error_cb_t report_error_cb);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Unregisters callback function handle.
|
||||
*
|
||||
* @return
|
||||
* 0 upon successful completion.
|
||||
* -EPERM unregister not permitted on NULL callback handle.
|
||||
*/
|
||||
int nv_unregister_error_cb(void);
|
||||
|
||||
#endif /* _NV_REPORT_ERR_H_ */
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nv-linux.h"
|
||||
#include "nv-rsync.h"
|
||||
|
||||
nv_rsync_info_t g_rsync_info;
|
||||
|
||||
void nv_init_rsync_info(
|
||||
void
|
||||
)
|
||||
{
|
||||
g_rsync_info.relaxed_ordering_mode = NV_FALSE;
|
||||
g_rsync_info.usage_count = 0;
|
||||
g_rsync_info.data = NULL;
|
||||
NV_INIT_MUTEX(&g_rsync_info.lock);
|
||||
}
|
||||
|
||||
void nv_destroy_rsync_info(
|
||||
void
|
||||
)
|
||||
{
|
||||
WARN_ON(g_rsync_info.data);
|
||||
WARN_ON(g_rsync_info.usage_count);
|
||||
WARN_ON(g_rsync_info.relaxed_ordering_mode);
|
||||
}
|
||||
|
||||
int nv_get_rsync_info(
|
||||
void
|
||||
)
|
||||
{
|
||||
int mode;
|
||||
int rc = 0;
|
||||
|
||||
down(&g_rsync_info.lock);
|
||||
|
||||
if (g_rsync_info.usage_count == 0)
|
||||
{
|
||||
if (g_rsync_info.get_relaxed_ordering_mode)
|
||||
{
|
||||
rc = g_rsync_info.get_relaxed_ordering_mode(&mode,
|
||||
g_rsync_info.data);
|
||||
if (rc != 0)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
g_rsync_info.relaxed_ordering_mode = !!mode;
|
||||
}
|
||||
}
|
||||
|
||||
g_rsync_info.usage_count++;
|
||||
|
||||
done:
|
||||
up(&g_rsync_info.lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void nv_put_rsync_info(
|
||||
void
|
||||
)
|
||||
{
|
||||
int mode;
|
||||
|
||||
down(&g_rsync_info.lock);
|
||||
|
||||
g_rsync_info.usage_count--;
|
||||
|
||||
if (g_rsync_info.usage_count == 0)
|
||||
{
|
||||
if (g_rsync_info.put_relaxed_ordering_mode)
|
||||
{
|
||||
mode = g_rsync_info.relaxed_ordering_mode;
|
||||
g_rsync_info.put_relaxed_ordering_mode(mode, g_rsync_info.data);
|
||||
g_rsync_info.relaxed_ordering_mode = NV_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
up(&g_rsync_info.lock);
|
||||
}
|
||||
|
||||
int nv_register_rsync_driver(
|
||||
int (*get_relaxed_ordering_mode)(int *mode, void *data),
|
||||
void (*put_relaxed_ordering_mode)(int mode, void *data),
|
||||
void (*wait_for_rsync)(struct pci_dev *gpu, void *data),
|
||||
void *data
|
||||
)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
down(&g_rsync_info.lock);
|
||||
|
||||
if (g_rsync_info.get_relaxed_ordering_mode != NULL)
|
||||
{
|
||||
rc = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (g_rsync_info.usage_count != 0)
|
||||
{
|
||||
rc = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
g_rsync_info.get_relaxed_ordering_mode = get_relaxed_ordering_mode;
|
||||
g_rsync_info.put_relaxed_ordering_mode = put_relaxed_ordering_mode;
|
||||
g_rsync_info.wait_for_rsync = wait_for_rsync;
|
||||
g_rsync_info.data = data;
|
||||
|
||||
done:
|
||||
up(&g_rsync_info.lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void nv_unregister_rsync_driver(
|
||||
int (*get_relaxed_ordering_mode)(int *mode, void *data),
|
||||
void (*put_relaxed_ordering_mode)(int mode, void *data),
|
||||
void (*wait_for_rsync)(struct pci_dev *gpu, void *data),
|
||||
void *data
|
||||
)
|
||||
{
|
||||
down(&g_rsync_info.lock);
|
||||
|
||||
WARN_ON(g_rsync_info.usage_count != 0);
|
||||
|
||||
WARN_ON(g_rsync_info.get_relaxed_ordering_mode !=
|
||||
get_relaxed_ordering_mode);
|
||||
WARN_ON(g_rsync_info.put_relaxed_ordering_mode !=
|
||||
put_relaxed_ordering_mode);
|
||||
WARN_ON(g_rsync_info.wait_for_rsync != wait_for_rsync);
|
||||
WARN_ON(g_rsync_info.data != data);
|
||||
|
||||
g_rsync_info.get_relaxed_ordering_mode = NULL;
|
||||
g_rsync_info.put_relaxed_ordering_mode = NULL;
|
||||
g_rsync_info.wait_for_rsync = NULL;
|
||||
g_rsync_info.data = NULL;
|
||||
|
||||
up(&g_rsync_info.lock);
|
||||
}
|
||||
|
||||
NvBool nv_get_rsync_relaxed_ordering_mode(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
/* shouldn't be called without opening a device */
|
||||
WARN_ON(NV_ATOMIC_READ(nvl->usage_count) == 0);
|
||||
|
||||
/*
|
||||
* g_rsync_info.relaxed_ordering_mode can be safely accessed outside of
|
||||
* g_rsync_info.lock once a device is opened. During nvidia_open(), we
|
||||
* lock the relaxed ordering state by ref-counting the rsync module
|
||||
* through get_relaxed_ordering_mode.
|
||||
*/
|
||||
return g_rsync_info.relaxed_ordering_mode;
|
||||
}
|
||||
|
||||
void nv_wait_for_rsync(
|
||||
nv_state_t *nv
|
||||
)
|
||||
{
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
|
||||
/* shouldn't be called without opening a device */
|
||||
WARN_ON(NV_ATOMIC_READ(nvl->usage_count) == 0);
|
||||
|
||||
/*
|
||||
* g_rsync_info.relaxed_ordering_mode can be safely accessed outside of
|
||||
* g_rsync_info.lock once a device is opened. During nvidia_open(), we
|
||||
* block unregistration of the rsync driver by ref-counting the module
|
||||
* through get_relaxed_ordering_mode.
|
||||
*/
|
||||
if (g_rsync_info.relaxed_ordering_mode)
|
||||
{
|
||||
WARN_ON(g_rsync_info.wait_for_rsync == NULL);
|
||||
g_rsync_info.wait_for_rsync(nvl->pci_dev, g_rsync_info.data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NV_RSYNC_H_
|
||||
#define _NV_RSYNC_H_
|
||||
|
||||
#include "nv-linux.h"
|
||||
|
||||
typedef struct nv_rsync_info
|
||||
{
|
||||
struct semaphore lock;
|
||||
uint32_t usage_count;
|
||||
NvBool relaxed_ordering_mode;
|
||||
int (*get_relaxed_ordering_mode)(int *mode, void *data);
|
||||
void (*put_relaxed_ordering_mode)(int mode, void *data);
|
||||
void (*wait_for_rsync)(struct pci_dev *gpu, void *data);
|
||||
void *data;
|
||||
} nv_rsync_info_t;
|
||||
|
||||
void nv_init_rsync_info(void);
|
||||
void nv_destroy_rsync_info(void);
|
||||
int nv_get_rsync_info(void);
|
||||
void nv_put_rsync_info(void);
|
||||
int nv_register_rsync_driver(
|
||||
int (*get_relaxed_ordering_mode)(int *mode, void *data),
|
||||
void (*put_relaxed_ordering_mode)(int mode, void *data),
|
||||
void (*wait_for_rsync)(struct pci_dev *gpu, void *data),
|
||||
void *data);
|
||||
void nv_unregister_rsync_driver(
|
||||
int (*get_relaxed_ordering_mode)(int *mode, void *data),
|
||||
void (*put_relaxed_ordering_mode)(int mode, void *data),
|
||||
void (*wait_for_rsync)(struct pci_dev *gpu, void *data),
|
||||
void *data);
|
||||
NvBool nv_get_rsync_relaxed_ordering_mode(nv_state_t *nv);
|
||||
void nv_wait_for_rsync(nv_state_t *nv);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-frontend.h"
|
||||
|
||||
NV_STATUS NV_API_CALL nv_add_mapping_context_to_file(
|
||||
nv_state_t *nv,
|
||||
nv_usermap_access_params_t *nvuap,
|
||||
NvU32 prot,
|
||||
void *pAllocPriv,
|
||||
NvU64 pageIndex,
|
||||
NvU32 fd
|
||||
)
|
||||
{
|
||||
NV_STATUS status = NV_OK;
|
||||
nv_alloc_mapping_context_t *nvamc = NULL;
|
||||
nv_file_private_t *nvfp = NULL;
|
||||
nv_linux_file_private_t *nvlfp = NULL;
|
||||
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
void *priv = NULL;
|
||||
|
||||
nvfp = nv_get_file_private(fd, NV_IS_CTL_DEVICE(nv), &priv);
|
||||
if (nvfp == NULL)
|
||||
return NV_ERR_INVALID_ARGUMENT;
|
||||
|
||||
nvlfp = nv_get_nvlfp_from_nvfp(nvfp);
|
||||
|
||||
nvamc = &nvlfp->mmap_context;
|
||||
|
||||
if (nvamc->valid)
|
||||
{
|
||||
status = NV_ERR_STATE_IN_USE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (NV_IS_CTL_DEVICE(nv))
|
||||
{
|
||||
nvamc->alloc = pAllocPriv;
|
||||
nvamc->page_index = pageIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NV_STATE_PTR(nvlfp->nvptr) != nv)
|
||||
{
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nvamc->mmap_start = nvuap->mmap_start;
|
||||
nvamc->mmap_size = nvuap->mmap_size;
|
||||
if (nv_get_numa_status(nvl) == NV_NUMA_STATUS_ONLINE)
|
||||
{
|
||||
nvamc->page_array = nvuap->page_array;
|
||||
nvamc->num_pages = nvuap->num_pages;
|
||||
}
|
||||
nvamc->access_start = nvuap->access_start;
|
||||
nvamc->access_size = nvuap->access_size;
|
||||
nvamc->remap_prot_extra = nvuap->remap_prot_extra;
|
||||
}
|
||||
|
||||
nvamc->prot = prot;
|
||||
nvamc->valid = NV_TRUE;
|
||||
nvamc->caching = nvuap->caching;
|
||||
|
||||
done:
|
||||
nv_put_file_private(priv);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_alloc_user_mapping(
|
||||
nv_state_t *nv,
|
||||
void *pAllocPrivate,
|
||||
NvU64 pageIndex,
|
||||
NvU32 pageOffset,
|
||||
NvU64 size,
|
||||
NvU32 protect,
|
||||
NvU64 *pUserAddress,
|
||||
void **ppPrivate
|
||||
)
|
||||
{
|
||||
nv_alloc_t *at = pAllocPrivate;
|
||||
|
||||
if (at->flags.contig)
|
||||
*pUserAddress = (at->page_table[0]->phys_addr + (pageIndex * PAGE_SIZE) + pageOffset);
|
||||
else
|
||||
*pUserAddress = (at->page_table[pageIndex]->phys_addr + pageOffset);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL nv_free_user_mapping(
|
||||
nv_state_t *nv,
|
||||
void *pAllocPrivate,
|
||||
NvU64 userAddress,
|
||||
void *pPrivate
|
||||
)
|
||||
{
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adjust the {mmap,access}_{start,size} to reflect platform-specific
|
||||
* mechanisms for isolating mappings at a finer granularity than the os_page_size
|
||||
*/
|
||||
NV_STATUS NV_API_CALL nv_get_usermap_access_params(
|
||||
nv_state_t *nv,
|
||||
nv_usermap_access_params_t *nvuap
|
||||
)
|
||||
{
|
||||
NvU64 addr = nvuap->addr;
|
||||
NvU64 size = nvuap->size;
|
||||
|
||||
nvuap->remap_prot_extra = 0;
|
||||
|
||||
/*
|
||||
* Do verification and cache encoding based on the original
|
||||
* (ostensibly smaller) mmap request, since accesses should be
|
||||
* restricted to that range.
|
||||
*/
|
||||
if (rm_gpu_need_4k_page_isolation(nv) &&
|
||||
NV_4K_PAGE_ISOLATION_REQUIRED(addr, size))
|
||||
{
|
||||
#if defined(NV_4K_PAGE_ISOLATION_PRESENT)
|
||||
nvuap->remap_prot_extra = NV_PROT_4K_PAGE_ISOLATION;
|
||||
nvuap->access_start = (NvU64)NV_4K_PAGE_ISOLATION_ACCESS_START(addr);
|
||||
nvuap->access_size = NV_4K_PAGE_ISOLATION_ACCESS_LEN(addr, size);
|
||||
nvuap->mmap_start = (NvU64)NV_4K_PAGE_ISOLATION_MMAP_ADDR(addr);
|
||||
nvuap->mmap_size = NV_4K_PAGE_ISOLATION_MMAP_LEN(size);
|
||||
#else
|
||||
NV_DEV_PRINTF(NV_DBG_ERRORS, nv, "4K page isolation required but not available!\n");
|
||||
return NV_ERR_OPERATING_SYSTEM;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
@@ -0,0 +1,703 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
static inline void nv_set_contig_memory_uc(nvidia_pte_t *page_ptr, NvU32 num_pages)
|
||||
{
|
||||
#if defined(NV_SET_MEMORY_UC_PRESENT)
|
||||
struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
|
||||
unsigned long addr = (unsigned long)page_address(page);
|
||||
set_memory_uc(addr, num_pages);
|
||||
#elif defined(NV_SET_PAGES_UC_PRESENT)
|
||||
struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
|
||||
set_pages_uc(page, num_pages);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void nv_set_contig_memory_wb(nvidia_pte_t *page_ptr, NvU32 num_pages)
|
||||
{
|
||||
#if defined(NV_SET_MEMORY_UC_PRESENT)
|
||||
struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
|
||||
unsigned long addr = (unsigned long)page_address(page);
|
||||
set_memory_wb(addr, num_pages);
|
||||
#elif defined(NV_SET_PAGES_UC_PRESENT)
|
||||
struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
|
||||
set_pages_wb(page, num_pages);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int nv_set_memory_array_type_present(NvU32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#if defined(NV_SET_MEMORY_ARRAY_UC_PRESENT)
|
||||
case NV_MEMORY_UNCACHED:
|
||||
return 1;
|
||||
case NV_MEMORY_WRITEBACK:
|
||||
return 1;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int nv_set_pages_array_type_present(NvU32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#if defined(NV_SET_PAGES_ARRAY_UC_PRESENT)
|
||||
case NV_MEMORY_UNCACHED:
|
||||
return 1;
|
||||
case NV_MEMORY_WRITEBACK:
|
||||
return 1;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nv_set_memory_array_type(
|
||||
unsigned long *pages,
|
||||
NvU32 num_pages,
|
||||
NvU32 type
|
||||
)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#if defined(NV_SET_MEMORY_ARRAY_UC_PRESENT)
|
||||
case NV_MEMORY_UNCACHED:
|
||||
set_memory_array_uc(pages, num_pages);
|
||||
break;
|
||||
case NV_MEMORY_WRITEBACK:
|
||||
set_memory_array_wb(pages, num_pages);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s(): type %d unimplemented\n",
|
||||
__FUNCTION__, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nv_set_pages_array_type(
|
||||
struct page **pages,
|
||||
NvU32 num_pages,
|
||||
NvU32 type
|
||||
)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#if defined(NV_SET_PAGES_ARRAY_UC_PRESENT)
|
||||
case NV_MEMORY_UNCACHED:
|
||||
set_pages_array_uc(pages, num_pages);
|
||||
break;
|
||||
case NV_MEMORY_WRITEBACK:
|
||||
set_pages_array_wb(pages, num_pages);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s(): type %d unimplemented\n",
|
||||
__FUNCTION__, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nv_set_contig_memory_type(
|
||||
nvidia_pte_t *page_ptr,
|
||||
NvU32 num_pages,
|
||||
NvU32 type
|
||||
)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case NV_MEMORY_UNCACHED:
|
||||
nv_set_contig_memory_uc(page_ptr, num_pages);
|
||||
break;
|
||||
case NV_MEMORY_WRITEBACK:
|
||||
nv_set_contig_memory_wb(page_ptr, num_pages);
|
||||
break;
|
||||
default:
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s(): type %d unimplemented\n",
|
||||
__FUNCTION__, type);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nv_set_memory_type(nv_alloc_t *at, NvU32 type)
|
||||
{
|
||||
NvU32 i;
|
||||
NV_STATUS status = NV_OK;
|
||||
#if defined(NV_SET_MEMORY_ARRAY_UC_PRESENT)
|
||||
unsigned long *pages = NULL;
|
||||
#elif defined(NV_SET_PAGES_ARRAY_UC_PRESENT)
|
||||
struct page **pages = NULL;
|
||||
#else
|
||||
unsigned long *pages = NULL;
|
||||
#endif
|
||||
|
||||
nvidia_pte_t *page_ptr;
|
||||
struct page *page;
|
||||
|
||||
if (nv_set_memory_array_type_present(type))
|
||||
{
|
||||
status = os_alloc_mem((void **)&pages,
|
||||
at->num_pages * sizeof(unsigned long));
|
||||
|
||||
}
|
||||
else if (nv_set_pages_array_type_present(type))
|
||||
{
|
||||
status = os_alloc_mem((void **)&pages,
|
||||
at->num_pages * sizeof(struct page*));
|
||||
}
|
||||
|
||||
if (status != NV_OK)
|
||||
pages = NULL;
|
||||
|
||||
//
|
||||
// If the set_{memory,page}_array_* functions are in the kernel interface,
|
||||
// it's faster to use them since they work on non-contiguous memory,
|
||||
// whereas the set_{memory,page}_* functions do not.
|
||||
//
|
||||
if (pages)
|
||||
{
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
{
|
||||
page_ptr = at->page_table[i];
|
||||
page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr);
|
||||
#if defined(NV_SET_MEMORY_ARRAY_UC_PRESENT)
|
||||
pages[i] = (unsigned long)page_address(page);
|
||||
#elif defined(NV_SET_PAGES_ARRAY_UC_PRESENT)
|
||||
pages[i] = page;
|
||||
#endif
|
||||
}
|
||||
#if defined(NV_SET_MEMORY_ARRAY_UC_PRESENT)
|
||||
nv_set_memory_array_type(pages, at->num_pages, type);
|
||||
#elif defined(NV_SET_PAGES_ARRAY_UC_PRESENT)
|
||||
nv_set_pages_array_type(pages, at->num_pages, type);
|
||||
#endif
|
||||
os_free_mem(pages);
|
||||
}
|
||||
|
||||
//
|
||||
// If the set_{memory,page}_array_* functions aren't present in the kernel
|
||||
// interface, each page has to be set individually, which has been measured
|
||||
// to be ~10x slower than using the set_{memory,page}_array_* functions.
|
||||
//
|
||||
else
|
||||
{
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
nv_set_contig_memory_type(at->page_table[i], 1, type);
|
||||
}
|
||||
}
|
||||
|
||||
static NvU64 nv_get_max_sysmem_address(void)
|
||||
{
|
||||
NvU64 global_max_pfn = 0ULL;
|
||||
int node_id;
|
||||
|
||||
for_each_online_node(node_id)
|
||||
{
|
||||
global_max_pfn = max(global_max_pfn, (NvU64)node_end_pfn(node_id));
|
||||
}
|
||||
|
||||
return ((global_max_pfn + 1) << PAGE_SHIFT) - 1;
|
||||
}
|
||||
|
||||
static unsigned int nv_compute_gfp_mask(
|
||||
nv_state_t *nv,
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
unsigned int gfp_mask = NV_GFP_KERNEL;
|
||||
struct device *dev = at->dev;
|
||||
|
||||
/*
|
||||
* If we know that SWIOTLB is enabled (and therefore we avoid calling the
|
||||
* kernel to DMA-remap the pages), or if we are using dma_direct (which may
|
||||
* transparently use the SWIOTLB for pages that are unaddressable by the
|
||||
* device, in kernel versions 5.0 and later), limit our allocation pool
|
||||
* to the first 4GB to avoid allocating pages outside of our device's
|
||||
* addressable limit.
|
||||
* Also, limit the allocation to the first 4GB if explicitly requested by
|
||||
* setting the "nv->force_dma32_alloc" variable.
|
||||
*/
|
||||
if (!nv || !nv_requires_dma_remap(nv) || nv_is_dma_direct(dev) || nv->force_dma32_alloc)
|
||||
{
|
||||
NvU64 max_sysmem_address = nv_get_max_sysmem_address();
|
||||
if ((dev && dev->dma_mask && (*(dev->dma_mask) < max_sysmem_address)) ||
|
||||
(nv && nv->force_dma32_alloc))
|
||||
{
|
||||
gfp_mask = NV_GFP_DMA32;
|
||||
}
|
||||
}
|
||||
#if defined(__GFP_RETRY_MAYFAIL)
|
||||
gfp_mask |= __GFP_RETRY_MAYFAIL;
|
||||
#elif defined(__GFP_NORETRY)
|
||||
gfp_mask |= __GFP_NORETRY;
|
||||
#endif
|
||||
#if defined(__GFP_ZERO)
|
||||
if (at->flags.zeroed)
|
||||
gfp_mask |= __GFP_ZERO;
|
||||
#endif
|
||||
#if defined(__GFP_THISNODE)
|
||||
if (at->flags.node)
|
||||
gfp_mask |= __GFP_THISNODE;
|
||||
#endif
|
||||
// Compound pages are required by vm_insert_page for high-order page
|
||||
// allocations
|
||||
if (at->order > 0)
|
||||
gfp_mask |= __GFP_COMP;
|
||||
|
||||
return gfp_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is needed for allocating contiguous physical memory in xen
|
||||
* dom0. Because of the use of xen sw iotlb in xen dom0, memory allocated by
|
||||
* NV_GET_FREE_PAGES may not be machine contiguous when size is more than
|
||||
* 1 page. nv_alloc_coherent_pages() will give us machine contiguous memory.
|
||||
* Even though we get dma_address directly in this function, we will
|
||||
* still call pci_map_page() later to get dma address. This is fine as it
|
||||
* will return the same machine address.
|
||||
*/
|
||||
static NV_STATUS nv_alloc_coherent_pages(
|
||||
nv_state_t *nv,
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
nvidia_pte_t *page_ptr;
|
||||
NvU32 i;
|
||||
unsigned int gfp_mask;
|
||||
unsigned long virt_addr = 0;
|
||||
dma_addr_t bus_addr;
|
||||
nv_linux_state_t *nvl;
|
||||
struct device *dev;
|
||||
|
||||
if (!nv)
|
||||
{
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: coherent page alloc on nvidiactl not supported\n", __FUNCTION__);
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
nvl = NV_GET_NVL_FROM_NV_STATE(nv);
|
||||
dev = nvl->dev;
|
||||
|
||||
gfp_mask = nv_compute_gfp_mask(nv, at);
|
||||
|
||||
virt_addr = (unsigned long)dma_alloc_coherent(dev,
|
||||
at->num_pages * PAGE_SIZE,
|
||||
&bus_addr,
|
||||
gfp_mask);
|
||||
if (!virt_addr)
|
||||
{
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: failed to allocate memory\n", __FUNCTION__);
|
||||
return NV_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
{
|
||||
page_ptr = at->page_table[i];
|
||||
|
||||
page_ptr->virt_addr = virt_addr + i * PAGE_SIZE;
|
||||
page_ptr->phys_addr = virt_to_phys((void *)page_ptr->virt_addr);
|
||||
page_ptr->dma_addr = bus_addr + i * PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (at->cache_type != NV_MEMORY_CACHED)
|
||||
{
|
||||
nv_set_contig_memory_type(at->page_table[0],
|
||||
at->num_pages,
|
||||
NV_MEMORY_UNCACHED);
|
||||
}
|
||||
|
||||
at->flags.coherent = NV_TRUE;
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
static void nv_free_coherent_pages(
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
nvidia_pte_t *page_ptr;
|
||||
struct device *dev = at->dev;
|
||||
|
||||
page_ptr = at->page_table[0];
|
||||
|
||||
if (at->cache_type != NV_MEMORY_CACHED)
|
||||
{
|
||||
nv_set_contig_memory_type(at->page_table[0],
|
||||
at->num_pages,
|
||||
NV_MEMORY_WRITEBACK);
|
||||
}
|
||||
|
||||
dma_free_coherent(dev, at->num_pages * PAGE_SIZE,
|
||||
(void *)page_ptr->virt_addr, page_ptr->dma_addr);
|
||||
}
|
||||
|
||||
NV_STATUS nv_alloc_contig_pages(
|
||||
nv_state_t *nv,
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
NV_STATUS status;
|
||||
nvidia_pte_t *page_ptr;
|
||||
NvU32 i, j;
|
||||
unsigned int gfp_mask;
|
||||
unsigned long virt_addr = 0;
|
||||
NvU64 phys_addr;
|
||||
struct device *dev = at->dev;
|
||||
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: %u pages\n", __FUNCTION__, at->num_pages);
|
||||
|
||||
// TODO: This is a temporary WAR, and will be removed after fixing bug 200732409.
|
||||
if (os_is_xen_dom0() || at->flags.unencrypted)
|
||||
return nv_alloc_coherent_pages(nv, at);
|
||||
|
||||
at->order = get_order(at->num_pages * PAGE_SIZE);
|
||||
gfp_mask = nv_compute_gfp_mask(nv, at);
|
||||
|
||||
if (at->flags.node)
|
||||
{
|
||||
NV_ALLOC_PAGES_NODE(virt_addr, at->node_id, at->order, gfp_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_GET_FREE_PAGES(virt_addr, at->order, gfp_mask);
|
||||
}
|
||||
if (virt_addr == 0)
|
||||
{
|
||||
if (os_is_vgx_hyper())
|
||||
{
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: failed to allocate memory, trying coherent memory \n", __FUNCTION__);
|
||||
|
||||
status = nv_alloc_coherent_pages(nv, at);
|
||||
return status;
|
||||
}
|
||||
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: failed to allocate memory\n", __FUNCTION__);
|
||||
return NV_ERR_NO_MEMORY;
|
||||
}
|
||||
#if !defined(__GFP_ZERO)
|
||||
if (at->flags.zeroed)
|
||||
memset((void *)virt_addr, 0, (at->num_pages * PAGE_SIZE));
|
||||
#endif
|
||||
|
||||
for (i = 0; i < at->num_pages; i++, virt_addr += PAGE_SIZE)
|
||||
{
|
||||
phys_addr = nv_get_kern_phys_address(virt_addr);
|
||||
if (phys_addr == 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: %s: failed to look up physical address\n",
|
||||
__FUNCTION__);
|
||||
status = NV_ERR_OPERATING_SYSTEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
page_ptr = at->page_table[i];
|
||||
page_ptr->phys_addr = phys_addr;
|
||||
page_ptr->page_count = NV_GET_PAGE_COUNT(page_ptr);
|
||||
page_ptr->virt_addr = virt_addr;
|
||||
page_ptr->dma_addr = nv_phys_to_dma(dev, page_ptr->phys_addr);
|
||||
|
||||
NV_MAYBE_RESERVE_PAGE(page_ptr);
|
||||
}
|
||||
|
||||
if (at->cache_type != NV_MEMORY_CACHED)
|
||||
{
|
||||
nv_set_contig_memory_type(at->page_table[0],
|
||||
at->num_pages,
|
||||
NV_MEMORY_UNCACHED);
|
||||
}
|
||||
|
||||
at->flags.coherent = NV_FALSE;
|
||||
|
||||
return NV_OK;
|
||||
|
||||
failed:
|
||||
if (i > 0)
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
NV_MAYBE_UNRESERVE_PAGE(at->page_table[j]);
|
||||
}
|
||||
|
||||
page_ptr = at->page_table[0];
|
||||
NV_FREE_PAGES(page_ptr->virt_addr, at->order);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void nv_free_contig_pages(
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
nvidia_pte_t *page_ptr;
|
||||
unsigned int i;
|
||||
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: %u pages\n", __FUNCTION__, at->num_pages);
|
||||
|
||||
if (at->flags.coherent)
|
||||
return nv_free_coherent_pages(at);
|
||||
|
||||
if (at->cache_type != NV_MEMORY_CACHED)
|
||||
{
|
||||
nv_set_contig_memory_type(at->page_table[0],
|
||||
at->num_pages,
|
||||
NV_MEMORY_WRITEBACK);
|
||||
}
|
||||
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
{
|
||||
page_ptr = at->page_table[i];
|
||||
|
||||
if (NV_GET_PAGE_COUNT(page_ptr) != page_ptr->page_count)
|
||||
{
|
||||
static int count = 0;
|
||||
if (count++ < NV_MAX_RECURRING_WARNING_MESSAGES)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: %s: page count != initial page count (%u,%u)\n",
|
||||
__FUNCTION__, NV_GET_PAGE_COUNT(page_ptr),
|
||||
page_ptr->page_count);
|
||||
}
|
||||
}
|
||||
NV_MAYBE_UNRESERVE_PAGE(page_ptr);
|
||||
}
|
||||
|
||||
page_ptr = at->page_table[0];
|
||||
|
||||
NV_FREE_PAGES(page_ptr->virt_addr, at->order);
|
||||
}
|
||||
|
||||
NV_STATUS nv_alloc_system_pages(
|
||||
nv_state_t *nv,
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
NV_STATUS status;
|
||||
nvidia_pte_t *page_ptr;
|
||||
NvU32 i, j;
|
||||
unsigned int gfp_mask;
|
||||
unsigned long virt_addr = 0;
|
||||
NvU64 phys_addr;
|
||||
struct device *dev = at->dev;
|
||||
dma_addr_t bus_addr;
|
||||
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %u: %u pages\n", __FUNCTION__, at->num_pages);
|
||||
|
||||
gfp_mask = nv_compute_gfp_mask(nv, at);
|
||||
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
{
|
||||
if (at->flags.unencrypted && (dev != NULL))
|
||||
{
|
||||
virt_addr = (unsigned long)dma_alloc_coherent(dev,
|
||||
PAGE_SIZE,
|
||||
&bus_addr,
|
||||
gfp_mask);
|
||||
at->flags.coherent = NV_TRUE;
|
||||
}
|
||||
else if (at->flags.node)
|
||||
{
|
||||
NV_ALLOC_PAGES_NODE(virt_addr, at->node_id, 0, gfp_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_GET_FREE_PAGES(virt_addr, 0, gfp_mask);
|
||||
}
|
||||
|
||||
if (virt_addr == 0)
|
||||
{
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: failed to allocate memory\n", __FUNCTION__);
|
||||
status = NV_ERR_NO_MEMORY;
|
||||
goto failed;
|
||||
}
|
||||
#if !defined(__GFP_ZERO)
|
||||
if (at->flags.zeroed)
|
||||
memset((void *)virt_addr, 0, PAGE_SIZE);
|
||||
#endif
|
||||
|
||||
phys_addr = nv_get_kern_phys_address(virt_addr);
|
||||
if (phys_addr == 0)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: %s: failed to look up physical address\n",
|
||||
__FUNCTION__);
|
||||
NV_FREE_PAGES(virt_addr, 0);
|
||||
status = NV_ERR_OPERATING_SYSTEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if defined(_PAGE_NX)
|
||||
if (((_PAGE_NX & pgprot_val(PAGE_KERNEL)) != 0) &&
|
||||
(phys_addr < 0x400000))
|
||||
{
|
||||
nv_printf(NV_DBG_SETUP,
|
||||
"NVRM: VM: %s: discarding page @ 0x%llx\n",
|
||||
__FUNCTION__, phys_addr);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
page_ptr = at->page_table[i];
|
||||
page_ptr->phys_addr = phys_addr;
|
||||
page_ptr->page_count = NV_GET_PAGE_COUNT(page_ptr);
|
||||
page_ptr->virt_addr = virt_addr;
|
||||
|
||||
//
|
||||
// Use unencrypted dma_addr returned by dma_alloc_coherent() as
|
||||
// nv_phys_to_dma() returns encrypted dma_addr when AMD SEV is enabled.
|
||||
//
|
||||
if (at->flags.coherent)
|
||||
page_ptr->dma_addr = bus_addr;
|
||||
else if (dev)
|
||||
page_ptr->dma_addr = nv_phys_to_dma(dev, page_ptr->phys_addr);
|
||||
else
|
||||
page_ptr->dma_addr = page_ptr->phys_addr;
|
||||
|
||||
NV_MAYBE_RESERVE_PAGE(page_ptr);
|
||||
}
|
||||
|
||||
if (at->cache_type != NV_MEMORY_CACHED)
|
||||
nv_set_memory_type(at, NV_MEMORY_UNCACHED);
|
||||
|
||||
return NV_OK;
|
||||
|
||||
failed:
|
||||
if (i > 0)
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
page_ptr = at->page_table[j];
|
||||
NV_MAYBE_UNRESERVE_PAGE(page_ptr);
|
||||
if (at->flags.coherent)
|
||||
{
|
||||
dma_free_coherent(dev, PAGE_SIZE, (void *)page_ptr->virt_addr,
|
||||
page_ptr->dma_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_FREE_PAGES(page_ptr->virt_addr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void nv_free_system_pages(
|
||||
nv_alloc_t *at
|
||||
)
|
||||
{
|
||||
nvidia_pte_t *page_ptr;
|
||||
unsigned int i;
|
||||
struct device *dev = at->dev;
|
||||
|
||||
nv_printf(NV_DBG_MEMINFO,
|
||||
"NVRM: VM: %s: %u pages\n", __FUNCTION__, at->num_pages);
|
||||
|
||||
if (at->cache_type != NV_MEMORY_CACHED)
|
||||
nv_set_memory_type(at, NV_MEMORY_WRITEBACK);
|
||||
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
{
|
||||
page_ptr = at->page_table[i];
|
||||
|
||||
if (NV_GET_PAGE_COUNT(page_ptr) != page_ptr->page_count)
|
||||
{
|
||||
static int count = 0;
|
||||
if (count++ < NV_MAX_RECURRING_WARNING_MESSAGES)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: VM: %s: page count != initial page count (%u,%u)\n",
|
||||
__FUNCTION__, NV_GET_PAGE_COUNT(page_ptr),
|
||||
page_ptr->page_count);
|
||||
}
|
||||
}
|
||||
|
||||
NV_MAYBE_UNRESERVE_PAGE(page_ptr);
|
||||
if (at->flags.coherent)
|
||||
{
|
||||
dma_free_coherent(dev, PAGE_SIZE, (void *)page_ptr->virt_addr,
|
||||
page_ptr->dma_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_FREE_PAGES(page_ptr->virt_addr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NvUPtr nv_vm_map_pages(
|
||||
struct page **pages,
|
||||
NvU32 count,
|
||||
NvBool cached,
|
||||
NvBool unencrypted
|
||||
)
|
||||
{
|
||||
NvUPtr virt_addr = 0;
|
||||
|
||||
if (!NV_MAY_SLEEP())
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s: can't map %d pages, invalid context!\n",
|
||||
__FUNCTION__, count);
|
||||
os_dbg_breakpoint();
|
||||
return virt_addr;
|
||||
}
|
||||
|
||||
virt_addr = nv_vmap(pages, count, cached, unencrypted);
|
||||
return virt_addr;
|
||||
}
|
||||
|
||||
void nv_vm_unmap_pages(
|
||||
NvUPtr virt_addr,
|
||||
NvU32 count
|
||||
)
|
||||
{
|
||||
if (!NV_MAY_SLEEP())
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s: can't unmap %d pages at 0x%0llx, "
|
||||
"invalid context!\n", __FUNCTION__, count, virt_addr);
|
||||
os_dbg_breakpoint();
|
||||
return;
|
||||
}
|
||||
|
||||
nv_vunmap(virt_addr, count);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2013 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
NvU64 NV_API_CALL nv_get_kern_phys_address(NvU64 address)
|
||||
{
|
||||
/* direct-mapped kernel address */
|
||||
if (virt_addr_valid(address))
|
||||
return __pa(address);
|
||||
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: can't translate address in %s()!\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2013-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* nv_gpu_ops.h
|
||||
*
|
||||
* This file defines the interface between the common RM layer
|
||||
* and the OS specific platform layers. (Currently supported
|
||||
* are Linux and KMD)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NV_GPU_OPS_H_
|
||||
#define _NV_GPU_OPS_H_
|
||||
#include "nvgputypes.h"
|
||||
#include "nv_uvm_types.h"
|
||||
|
||||
typedef struct gpuSession *gpuSessionHandle;
|
||||
typedef struct gpuDevice *gpuDeviceHandle;
|
||||
typedef struct gpuAddressSpace *gpuAddressSpaceHandle;
|
||||
typedef struct gpuTsg *gpuTsgHandle;
|
||||
typedef struct gpuChannel *gpuChannelHandle;
|
||||
typedef struct gpuObject *gpuObjectHandle;
|
||||
|
||||
typedef struct gpuRetainedChannel_struct gpuRetainedChannel;
|
||||
|
||||
NV_STATUS nvGpuOpsCreateSession(struct gpuSession **session);
|
||||
|
||||
NV_STATUS nvGpuOpsDestroySession(struct gpuSession *session);
|
||||
|
||||
NV_STATUS nvGpuOpsDeviceCreate(struct gpuSession *session,
|
||||
const gpuInfo *pGpuInfo,
|
||||
const NvProcessorUuid *gpuGuid,
|
||||
struct gpuDevice **device,
|
||||
NvBool bCreateSmcPartition);
|
||||
|
||||
NV_STATUS nvGpuOpsDeviceDestroy(struct gpuDevice *device);
|
||||
|
||||
NV_STATUS nvGpuOpsAddressSpaceCreate(struct gpuDevice *device,
|
||||
NvU64 vaBase,
|
||||
NvU64 vaSize,
|
||||
gpuAddressSpaceHandle *vaSpace,
|
||||
UvmGpuAddressSpaceInfo *vaSpaceInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsGetP2PCaps(gpuDeviceHandle device1,
|
||||
gpuDeviceHandle device2,
|
||||
getP2PCapsParams *p2pCaps);
|
||||
|
||||
void nvGpuOpsAddressSpaceDestroy(gpuAddressSpaceHandle vaSpace);
|
||||
|
||||
NV_STATUS nvGpuOpsMemoryAllocFb (gpuAddressSpaceHandle vaSpace,
|
||||
NvLength length, NvU64 *gpuOffset, gpuAllocInfo * allocInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsMemoryAllocSys (gpuAddressSpaceHandle vaSpace,
|
||||
NvLength length, NvU64 *gpuOffset, gpuAllocInfo * allocInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsPmaAllocPages(void *pPma,
|
||||
NvLength pageCount,
|
||||
NvU64 pageSize,
|
||||
gpuPmaAllocationOptions *pPmaAllocOptions,
|
||||
NvU64 *pPages);
|
||||
|
||||
void nvGpuOpsPmaFreePages(void *pPma,
|
||||
NvU64 *pPages,
|
||||
NvLength pageCount,
|
||||
NvU64 pageSize,
|
||||
NvU32 flags);
|
||||
|
||||
NV_STATUS nvGpuOpsPmaPinPages(void *pPma,
|
||||
NvU64 *pPages,
|
||||
NvLength pageCount,
|
||||
NvU64 pageSize,
|
||||
NvU32 flags);
|
||||
|
||||
NV_STATUS nvGpuOpsPmaUnpinPages(void *pPma,
|
||||
NvU64 *pPages,
|
||||
NvLength pageCount,
|
||||
NvU64 pageSize);
|
||||
|
||||
NV_STATUS nvGpuOpsTsgAllocate(gpuAddressSpaceHandle vaSpace,
|
||||
const gpuTsgAllocParams *params,
|
||||
gpuTsgHandle *tsgHandle);
|
||||
|
||||
NV_STATUS nvGpuOpsChannelAllocate(const gpuTsgHandle tsgHandle,
|
||||
const gpuChannelAllocParams *params,
|
||||
gpuChannelHandle *channelHandle,
|
||||
gpuChannelInfo *channelInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsMemoryReopen(struct gpuAddressSpace *vaSpace,
|
||||
NvHandle hSrcClient, NvHandle hSrcAllocation, NvLength length, NvU64 *gpuOffset);
|
||||
|
||||
void nvGpuOpsTsgDestroy(struct gpuTsg *tsg);
|
||||
|
||||
void nvGpuOpsChannelDestroy(struct gpuChannel *channel);
|
||||
|
||||
void nvGpuOpsMemoryFree(gpuAddressSpaceHandle vaSpace,
|
||||
NvU64 pointer);
|
||||
|
||||
NV_STATUS nvGpuOpsMemoryCpuMap(gpuAddressSpaceHandle vaSpace,
|
||||
NvU64 memory, NvLength length,
|
||||
void **cpuPtr, NvU64 pageSize);
|
||||
|
||||
void nvGpuOpsMemoryCpuUnMap(gpuAddressSpaceHandle vaSpace,
|
||||
void* cpuPtr);
|
||||
|
||||
NV_STATUS nvGpuOpsQueryCaps(struct gpuDevice *device,
|
||||
gpuCaps *caps);
|
||||
|
||||
NV_STATUS nvGpuOpsQueryCesCaps(struct gpuDevice *device,
|
||||
gpuCesCaps *caps);
|
||||
|
||||
NV_STATUS nvGpuOpsDupAllocation(struct gpuAddressSpace *srcVaSpace,
|
||||
NvU64 srcAddress,
|
||||
struct gpuAddressSpace *dstVaSpace,
|
||||
NvU64 dstVaAlignment,
|
||||
NvU64 *dstAddress);
|
||||
|
||||
NV_STATUS nvGpuOpsDupMemory(struct gpuDevice *device,
|
||||
NvHandle hClient,
|
||||
NvHandle hPhysMemory,
|
||||
NvHandle *hDupMemory,
|
||||
gpuMemoryInfo *pGpuMemoryInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsGetGuid(NvHandle hClient, NvHandle hDevice,
|
||||
NvHandle hSubDevice, NvU8 *gpuGuid,
|
||||
unsigned guidLength);
|
||||
|
||||
NV_STATUS nvGpuOpsGetClientInfoFromPid(unsigned pid,
|
||||
const NvU8 *gpuUuid,
|
||||
NvHandle *hClient,
|
||||
NvHandle *hDevice,
|
||||
NvHandle *hSubDevice);
|
||||
|
||||
NV_STATUS nvGpuOpsFreeDupedHandle(struct gpuDevice *device,
|
||||
NvHandle hPhysHandle);
|
||||
|
||||
NV_STATUS nvGpuOpsGetAttachedGpus(NvU8 *guidList, unsigned *numGpus);
|
||||
|
||||
NV_STATUS nvGpuOpsGetGpuInfo(const NvProcessorUuid *gpuUuid,
|
||||
const gpuClientInfo *pGpuClientInfo,
|
||||
gpuInfo *pGpuInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsGetGpuIds(const NvU8 *pUuid, unsigned uuidLength, NvU32 *pDeviceId,
|
||||
NvU32 *pSubdeviceId);
|
||||
|
||||
NV_STATUS nvGpuOpsOwnPageFaultIntr(struct gpuDevice *device, NvBool bOwnInterrupts);
|
||||
|
||||
NV_STATUS nvGpuOpsServiceDeviceInterruptsRM(struct gpuDevice *device);
|
||||
|
||||
NV_STATUS nvGpuOpsCheckEccErrorSlowpath(struct gpuChannel * channel, NvBool *bEccDbeSet);
|
||||
|
||||
NV_STATUS nvGpuOpsSetPageDirectory(struct gpuAddressSpace * vaSpace,
|
||||
NvU64 physAddress, unsigned numEntries,
|
||||
NvBool bVidMemAperture, NvU32 pasid);
|
||||
|
||||
NV_STATUS nvGpuOpsUnsetPageDirectory(struct gpuAddressSpace * vaSpace);
|
||||
|
||||
NV_STATUS nvGpuOpsGetGmmuFmt(struct gpuAddressSpace * vaSpace, void ** pFmt);
|
||||
|
||||
NV_STATUS nvGpuOpsInvalidateTlb(struct gpuAddressSpace * vaSpace);
|
||||
|
||||
NV_STATUS nvGpuOpsGetFbInfo(struct gpuDevice *device, gpuFbInfo * fbInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsGetEccInfo(struct gpuDevice *device, gpuEccInfo * eccInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsInitFaultInfo(struct gpuDevice *device, gpuFaultInfo *pFaultInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsDestroyFaultInfo(struct gpuDevice *device,
|
||||
gpuFaultInfo *pFaultInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsHasPendingNonReplayableFaults(gpuFaultInfo *pFaultInfo, NvBool *hasPendingFaults);
|
||||
|
||||
NV_STATUS nvGpuOpsGetNonReplayableFaults(gpuFaultInfo *pFaultInfo, void *faultBuffer, NvU32 *numFaults);
|
||||
|
||||
NV_STATUS nvGpuOpsDupAddressSpace(struct gpuDevice *device,
|
||||
NvHandle hUserClient,
|
||||
NvHandle hUserVASpace,
|
||||
struct gpuAddressSpace **vaSpace,
|
||||
UvmGpuAddressSpaceInfo *vaSpaceInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsGetPmaObject(struct gpuDevice *device,
|
||||
void **pPma,
|
||||
const UvmPmaStatistics **pPmaPubStats);
|
||||
|
||||
NV_STATUS nvGpuOpsInitAccessCntrInfo(struct gpuDevice *device, gpuAccessCntrInfo *pAccessCntrInfo, NvU32 accessCntrIndex);
|
||||
|
||||
NV_STATUS nvGpuOpsDestroyAccessCntrInfo(struct gpuDevice *device,
|
||||
gpuAccessCntrInfo *pAccessCntrInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsOwnAccessCntrIntr(struct gpuSession *session,
|
||||
gpuAccessCntrInfo *pAccessCntrInfo,
|
||||
NvBool bOwnInterrupts);
|
||||
|
||||
NV_STATUS nvGpuOpsEnableAccessCntr(struct gpuDevice *device,
|
||||
gpuAccessCntrInfo *pAccessCntrInfo,
|
||||
gpuAccessCntrConfig *pAccessCntrConfig);
|
||||
|
||||
NV_STATUS nvGpuOpsDisableAccessCntr(struct gpuDevice *device, gpuAccessCntrInfo *pAccessCntrInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsP2pObjectCreate(struct gpuDevice *device1,
|
||||
struct gpuDevice *device2,
|
||||
NvHandle *hP2pObject);
|
||||
|
||||
NV_STATUS nvGpuOpsP2pObjectDestroy(struct gpuSession *session,
|
||||
NvHandle hP2pObject);
|
||||
|
||||
NV_STATUS nvGpuOpsGetExternalAllocPtes(struct gpuAddressSpace *vaSpace,
|
||||
NvHandle hDupedMemory,
|
||||
NvU64 offset,
|
||||
NvU64 size,
|
||||
gpuExternalMappingInfo *pGpuExternalMappingInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsRetainChannel(struct gpuAddressSpace *vaSpace,
|
||||
NvHandle hClient,
|
||||
NvHandle hChannel,
|
||||
gpuRetainedChannel **retainedChannel,
|
||||
gpuChannelInstanceInfo *channelInstanceInfo);
|
||||
|
||||
void nvGpuOpsReleaseChannel(gpuRetainedChannel *retainedChannel);
|
||||
|
||||
NV_STATUS nvGpuOpsBindChannelResources(gpuRetainedChannel *retainedChannel,
|
||||
gpuChannelResourceBindParams *channelResourceBindParams);
|
||||
|
||||
void nvGpuOpsStopChannel(gpuRetainedChannel *retainedChannel, NvBool bImmediate);
|
||||
|
||||
NV_STATUS nvGpuOpsGetChannelResourcePtes(struct gpuAddressSpace *vaSpace,
|
||||
NvP64 resourceDescriptor,
|
||||
NvU64 offset,
|
||||
NvU64 size,
|
||||
gpuExternalMappingInfo *pGpuExternalMappingInfo);
|
||||
|
||||
NV_STATUS nvGpuOpsReportNonReplayableFault(struct gpuDevice *device,
|
||||
const void *pFaultPacket);
|
||||
|
||||
// Private interface used for windows only
|
||||
|
||||
#if defined(NV_WINDOWS)
|
||||
NV_STATUS nvGpuOpsGetRmHandleForSession(gpuSessionHandle hSession, NvHandle *hRmClient);
|
||||
|
||||
NV_STATUS nvGpuOpsGetRmHandleForChannel(gpuChannelHandle hChannel, NvHandle *hRmChannel);
|
||||
#endif // WINDOWS
|
||||
|
||||
// Interface used for SR-IOV heavy
|
||||
|
||||
NV_STATUS nvGpuOpsPagingChannelAllocate(struct gpuDevice *device,
|
||||
const gpuPagingChannelAllocParams *params,
|
||||
gpuPagingChannelHandle *channelHandle,
|
||||
gpuPagingChannelInfo *channelinfo);
|
||||
|
||||
void nvGpuOpsPagingChannelDestroy(UvmGpuPagingChannel *channel);
|
||||
|
||||
NV_STATUS nvGpuOpsPagingChannelsMap(struct gpuAddressSpace *srcVaSpace,
|
||||
NvU64 srcAddress,
|
||||
struct gpuDevice *device,
|
||||
NvU64 *dstAddress);
|
||||
|
||||
void nvGpuOpsPagingChannelsUnmap(struct gpuAddressSpace *srcVaSpace,
|
||||
NvU64 srcAddress,
|
||||
struct gpuDevice *device);
|
||||
|
||||
NV_STATUS nvGpuOpsPagingChannelPushStream(UvmGpuPagingChannel *channel,
|
||||
char *methodStream,
|
||||
NvU32 methodStreamSize);
|
||||
|
||||
NV_STATUS nvGpuOpsFlushReplayableFaultBuffer(struct gpuDevice *device);
|
||||
|
||||
// Interface used for CCSL
|
||||
|
||||
NV_STATUS nvGpuOpsCcslContextInit(struct ccslContext_t **ctx,
|
||||
gpuChannelHandle channel);
|
||||
NV_STATUS nvGpuOpsCcslContextClear(struct ccslContext_t *ctx);
|
||||
NV_STATUS nvGpuOpsCcslRotateIv(struct ccslContext_t *ctx,
|
||||
NvU8 direction);
|
||||
NV_STATUS nvGpuOpsCcslEncrypt(struct ccslContext_t *ctx,
|
||||
NvU32 bufferSize,
|
||||
NvU8 const *inputBuffer,
|
||||
NvU8 *outputBuffer,
|
||||
NvU8 *authTagBuffer);
|
||||
NV_STATUS nvGpuOpsCcslEncryptWithIv(struct ccslContext_t *ctx,
|
||||
NvU32 bufferSize,
|
||||
NvU8 const *inputBuffer,
|
||||
NvU8 *encryptIv,
|
||||
NvU8 *outputBuffer,
|
||||
NvU8 *authTagBuffer);
|
||||
NV_STATUS nvGpuOpsCcslDecrypt(struct ccslContext_t *ctx,
|
||||
NvU32 bufferSize,
|
||||
NvU8 const *inputBuffer,
|
||||
NvU8 const *decryptIv,
|
||||
NvU8 *outputBuffer,
|
||||
NvU8 const *addAuthData,
|
||||
NvU32 addAuthDataSize,
|
||||
NvU8 const *authTagBuffer);
|
||||
NV_STATUS nvGpuOpsCcslSign(struct ccslContext_t *ctx,
|
||||
NvU32 bufferSize,
|
||||
NvU8 const *inputBuffer,
|
||||
NvU8 *authTagBuffer);
|
||||
NV_STATUS nvGpuOpsQueryMessagePool(struct ccslContext_t *ctx,
|
||||
NvU8 direction,
|
||||
NvU64 *messageNum);
|
||||
NV_STATUS nvGpuOpsIncrementIv(struct ccslContext_t *ctx,
|
||||
NvU8 direction,
|
||||
NvU64 increment,
|
||||
NvU8 *iv);
|
||||
|
||||
#endif /* _NV_GPU_OPS_H_*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
NVIDIA_SOURCES ?=
|
||||
NVIDIA_SOURCES_CXX ?=
|
||||
|
||||
NVIDIA_SOURCES += nvidia/nv.c
|
||||
NVIDIA_SOURCES += nvidia/nv-pci.c
|
||||
NVIDIA_SOURCES += nvidia/nv-dmabuf.c
|
||||
NVIDIA_SOURCES += nvidia/nv-nano-timer.c
|
||||
NVIDIA_SOURCES += nvidia/nv-acpi.c
|
||||
NVIDIA_SOURCES += nvidia/nv-cray.c
|
||||
NVIDIA_SOURCES += nvidia/nv-dma.c
|
||||
NVIDIA_SOURCES += nvidia/nv-i2c.c
|
||||
NVIDIA_SOURCES += nvidia/nv-mmap.c
|
||||
NVIDIA_SOURCES += nvidia/nv-p2p.c
|
||||
NVIDIA_SOURCES += nvidia/nv-pat.c
|
||||
NVIDIA_SOURCES += nvidia/nv-procfs.c
|
||||
NVIDIA_SOURCES += nvidia/nv-usermap.c
|
||||
NVIDIA_SOURCES += nvidia/nv-vm.c
|
||||
NVIDIA_SOURCES += nvidia/nv-vtophys.c
|
||||
NVIDIA_SOURCES += nvidia/os-interface.c
|
||||
NVIDIA_SOURCES += nvidia/os-mlock.c
|
||||
NVIDIA_SOURCES += nvidia/os-pci.c
|
||||
NVIDIA_SOURCES += nvidia/os-registry.c
|
||||
NVIDIA_SOURCES += nvidia/os-usermap.c
|
||||
NVIDIA_SOURCES += nvidia/nv-modeset-interface.c
|
||||
NVIDIA_SOURCES += nvidia/nv-pci-table.c
|
||||
NVIDIA_SOURCES += nvidia/nv-kthread-q.c
|
||||
NVIDIA_SOURCES += nvidia/nv-memdbg.c
|
||||
NVIDIA_SOURCES += nvidia/nv-ibmnpu.c
|
||||
NVIDIA_SOURCES += nvidia/nv-report-err.c
|
||||
NVIDIA_SOURCES += nvidia/nv-rsync.c
|
||||
NVIDIA_SOURCES += nvidia/nv-msi.c
|
||||
NVIDIA_SOURCES += nvidia/nv-caps.c
|
||||
NVIDIA_SOURCES += nvidia/nv-frontend.c
|
||||
NVIDIA_SOURCES += nvidia/nv_uvm_interface.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_aead.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_ecc.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_hkdf.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_rand.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_shash.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_aead_aes_gcm.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_sha.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_hmac_sha.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_hkdf_sha.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_ec.c
|
||||
NVIDIA_SOURCES += nvidia/libspdm_x509.c
|
||||
NVIDIA_SOURCES += nvidia/nvlink_linux.c
|
||||
NVIDIA_SOURCES += nvidia/nvlink_caps.c
|
||||
NVIDIA_SOURCES += nvidia/linux_nvswitch.c
|
||||
NVIDIA_SOURCES += nvidia/procfs_nvswitch.c
|
||||
NVIDIA_SOURCES += nvidia/i2c_nvswitch.c
|
||||
@@ -0,0 +1,270 @@
|
||||
###########################################################################
|
||||
# Kbuild fragment for nvidia.ko
|
||||
###########################################################################
|
||||
|
||||
#
|
||||
# Define NVIDIA_{SOURCES,OBJECTS}
|
||||
#
|
||||
|
||||
include $(src)/nvidia/nvidia-sources.Kbuild
|
||||
NVIDIA_OBJECTS = $(patsubst %.c,%.o,$(NVIDIA_SOURCES))
|
||||
|
||||
obj-m += nvidia.o
|
||||
nvidia-y := $(NVIDIA_OBJECTS)
|
||||
|
||||
NVIDIA_KO = nvidia/nvidia.ko
|
||||
|
||||
|
||||
#
|
||||
# nv-kernel.o_binary is the core binary component of nvidia.ko, shared
|
||||
# across all UNIX platforms. Create a symlink, "nv-kernel.o" that
|
||||
# points to nv-kernel.o_binary, and add nv-kernel.o to the list of
|
||||
# objects to link into nvidia.ko.
|
||||
#
|
||||
# Note that:
|
||||
# - The kbuild "clean" rule will delete all objects in nvidia-y (which
|
||||
# is why we use a symlink instead of just adding nv-kernel.o_binary
|
||||
# to nvidia-y).
|
||||
# - kbuild normally uses the naming convention of ".o_shipped" for
|
||||
# binary files. That is not used here, because the kbuild rule to
|
||||
# create the "normal" object file from ".o_shipped" does a copy, not
|
||||
# a symlink. This file is quite large, so a symlink is preferred.
|
||||
# - The file added to nvidia-y should be relative to gmake's cwd.
|
||||
# But, the target for the symlink rule should be prepended with $(obj).
|
||||
# - The "symlink" command is called using kbuild's if_changed macro to
|
||||
# generate an .nv-kernel.o.cmd file which can be used on subsequent
|
||||
# runs to determine if the command line to create the symlink changed
|
||||
# and needs to be re-executed.
|
||||
#
|
||||
|
||||
NVIDIA_BINARY_OBJECT := $(src)/nvidia/nv-kernel.o_binary
|
||||
NVIDIA_BINARY_OBJECT_O := nvidia/nv-kernel.o
|
||||
|
||||
quiet_cmd_symlink = SYMLINK $@
|
||||
cmd_symlink = ln -sf $< $@
|
||||
|
||||
targets += $(NVIDIA_BINARY_OBJECT_O)
|
||||
|
||||
$(obj)/$(NVIDIA_BINARY_OBJECT_O): $(NVIDIA_BINARY_OBJECT) FORCE
|
||||
$(call if_changed,symlink)
|
||||
|
||||
nvidia-y += $(NVIDIA_BINARY_OBJECT_O)
|
||||
|
||||
|
||||
#
|
||||
# Define nvidia.ko-specific CFLAGS.
|
||||
#
|
||||
|
||||
NVIDIA_CFLAGS += -I$(src)/nvidia
|
||||
NVIDIA_CFLAGS += -DNVIDIA_UNDEF_LEGACY_BIT_MACROS
|
||||
|
||||
ifeq ($(NV_BUILD_TYPE),release)
|
||||
NVIDIA_CFLAGS += -UDEBUG -U_DEBUG -DNDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(NV_BUILD_TYPE),develop)
|
||||
NVIDIA_CFLAGS += -UDEBUG -U_DEBUG -DNDEBUG -DNV_MEM_LOGGER
|
||||
endif
|
||||
|
||||
ifeq ($(NV_BUILD_TYPE),debug)
|
||||
NVIDIA_CFLAGS += -DDEBUG -D_DEBUG -UNDEBUG -DNV_MEM_LOGGER
|
||||
endif
|
||||
|
||||
$(call ASSIGN_PER_OBJ_CFLAGS, $(NVIDIA_OBJECTS), $(NVIDIA_CFLAGS))
|
||||
|
||||
|
||||
#
|
||||
# nv-procfs.c requires nv-compiler.h
|
||||
#
|
||||
|
||||
NV_COMPILER_VERSION_HEADER = $(obj)/nv_compiler.h
|
||||
|
||||
$(NV_COMPILER_VERSION_HEADER):
|
||||
@echo \#define NV_COMPILER \"`$(CC) -v 2>&1 | tail -n 1`\" > $@
|
||||
|
||||
$(obj)/nvidia/nv-procfs.o: $(NV_COMPILER_VERSION_HEADER)
|
||||
|
||||
clean-files += $(NV_COMPILER_VERSION_HEADER)
|
||||
|
||||
|
||||
#
|
||||
# Build nv-interface.o from the kernel interface layer objects, suitable
|
||||
# for further processing by the top-level makefile to produce a precompiled
|
||||
# kernel interface file.
|
||||
#
|
||||
|
||||
NVIDIA_INTERFACE := nvidia/nv-interface.o
|
||||
|
||||
# Linux kernel v5.12 and later looks at "always-y", Linux kernel versions
|
||||
# before v5.6 looks at "always"; kernel versions between v5.12 and v5.6
|
||||
# look at both.
|
||||
|
||||
always += $(NVIDIA_INTERFACE)
|
||||
always-y += $(NVIDIA_INTERFACE)
|
||||
|
||||
$(obj)/$(NVIDIA_INTERFACE): $(addprefix $(obj)/,$(NVIDIA_OBJECTS))
|
||||
$(LD) -r -o $@ $^
|
||||
|
||||
|
||||
#
|
||||
# Register the conftests needed by nvidia.ko
|
||||
#
|
||||
|
||||
NV_OBJECTS_DEPEND_ON_CONFTEST += $(NVIDIA_OBJECTS)
|
||||
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += hash__remap_4k_pfn
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_pages_uc
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += list_is_first
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_memory_uc
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_memory_array_uc
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_pages_array_uc
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_cache
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_wc
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_driver_hardened
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_driver_hardened_wc
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_cache_shared
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_get_domain_bus_and_slot
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_num_physpages
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pde_data
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += xen_ioemu_inject_msi
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += phys_to_dma
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_dma_ops
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_attr_macros
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_map_page_attrs
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += write_cr4
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_find_node_by_phandle
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_node_to_nid
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pnv_pci_get_npu_dev
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_get_ibm_chip_id
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_bus_address
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_stop_and_remove_bus_device
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_rebar_get_possible_sizes
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += wait_for_random_bytes
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += register_cpu_notifier
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += cpuhp_setup_state
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_map_resource
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_backlight_device_by_name
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += timer_setup
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_enable_msix_range
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += kernel_read_has_pointer_pos_arg
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += kernel_write_has_pointer_pos_arg
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_direct_map_resource
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += tegra_get_platform
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += tegra_bpmp_send_receive
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += flush_cache_all
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += vmf_insert_pfn
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += jiffies_to_timespec
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ktime_get_raw_ts64
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += ktime_get_real_ts64
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += full_name_hash
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_enable_atomic_ops_to_root
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += vga_tryget
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += cc_platform_has
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += seq_read_iter
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += unsafe_follow_pfn
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_gem_object_get
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_gem_object_put_unlocked
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += add_memory_driver_managed
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += device_property_read_u64
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += devm_of_platform_populate
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_dma_configure
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_property_count_elems_of_size
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_property_read_variable_u8_array
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_property_read_variable_u32_array
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += i2c_new_client_device
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += i2c_unregister_device
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += of_get_named_gpio
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += devm_gpio_request_one
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_direction_input
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_direction_output
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_get_value
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_set_value
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_to_irq
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += icc_get
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += icc_put
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += icc_set_bw
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_export_args
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_ops_has_kmap
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_ops_has_kmap_atomic
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_ops_has_map
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_ops_has_map_atomic
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_has_dynamic_attachment
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_buf_attachment_has_peer2peer
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += dma_set_mask_and_coherent
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += devm_clk_bulk_get_all
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_task_ioprio
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += mdev_set_iommu_device
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += offline_and_remove_memory
|
||||
NV_CONFTEST_FUNCTION_COMPILE_TESTS += crypto_tfm_ctx_aligned
|
||||
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_of_node_to_nid
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_sme_active
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_swiotlb_map_sg_attrs
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_swiotlb_dma_ops
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present___close_fd
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_close_fd
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_get_unused_fd
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_get_unused_fd_flags
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_nvhost_get_default_device
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_nvhost_syncpt_unit_interface_get_byte_offset
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_nvhost_syncpt_unit_interface_get_aperture
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tegra_dce_register_ipc_client
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tegra_dce_unregister_ipc_client
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tegra_dce_client_ipc_send_recv
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_dram_clk_to_mc_clk
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_get_dram_num_channels
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tegra_dram_types
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_pxm_to_node
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_screen_info
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_screen_info
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_i2c_bus_status
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tegra_fuse_control_read
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tegra_get_platform
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_pci_find_host_bridge
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_send_cmd
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_set_init_cb
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_clear_init_cb
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_alloc_mem_from_gscco
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_tsec_comms_free_gscco_mem
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_memory_block_size_bytes
|
||||
NV_CONFTEST_SYMBOL_COMPILE_TESTS += crypto
|
||||
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += dma_ops
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += swiotlb_dma_ops
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += noncoherent_swiotlb_dma_ops
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_fault_has_address
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_insert_pfn_prot
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += vmf_insert_pfn_prot
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_ops_fault_removed_vma_arg
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += kmem_cache_has_kobj_remove_work
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += sysfs_slab_unlink
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += proc_ops
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += timespec64
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += vmalloc_has_pgprot_t_arg
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += mm_has_mmap_lock
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += pci_channel_state
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += pci_dev_has_ats_enabled
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += remove_memory_has_nid_arg
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += add_memory_driver_managed_has_mhp_flags_arg
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += num_registered_fb
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += pci_driver_has_driver_managed_dma
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_const_vm_flags
|
||||
NV_CONFTEST_TYPE_COMPILE_TESTS += memory_failure_has_trapno_arg
|
||||
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += dom0_kernel_present
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += nvidia_vgpu_kvm_build
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += nvidia_grid_build
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += nvidia_grid_csp_build
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += get_user_pages
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += get_user_pages_remote
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += pin_user_pages
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += pin_user_pages_remote
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += pm_runtime_available
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += vm_fault_t
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += pci_class_multimedia_hd_audio
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += drm_available
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += vfio_pci_core_available
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += mdev_available
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += cmd_uphy_display_port_init
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += cmd_uphy_display_port_off
|
||||
NV_CONFTEST_GENERIC_COMPILE_TESTS += memory_failure_mf_sw_simulated_defined
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "nvlink_os.h"
|
||||
#include "nvlink_linux.h"
|
||||
#include "nvlink_caps.h"
|
||||
#include "nv-caps.h"
|
||||
|
||||
#define NVLINK_CAP_FABRIC_MGMT "fabric-mgmt"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nv_cap_t *root;
|
||||
nv_cap_t *fabric_mgmt;
|
||||
} nvlink_caps_t;
|
||||
|
||||
static nvlink_caps_t nvlink_caps = {0};
|
||||
|
||||
int nvlink_cap_acquire(int fd, NvU32 type)
|
||||
{
|
||||
int dup_fd = -1;
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case NVLINK_CAP_FABRIC_MANAGEMENT:
|
||||
{
|
||||
dup_fd = nv_cap_validate_and_dup_fd(nvlink_caps.fabric_mgmt, fd);
|
||||
if (dup_fd < 0)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS,
|
||||
"Failed to validate the fabric mgmt capability\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "Unknown capability specified\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return dup_fd;
|
||||
}
|
||||
|
||||
void nvlink_cap_release(int fd)
|
||||
{
|
||||
if (fd < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nv_cap_close_fd(fd);
|
||||
}
|
||||
|
||||
void nvlink_cap_exit(void)
|
||||
{
|
||||
if (nvlink_caps.fabric_mgmt != NULL)
|
||||
{
|
||||
nv_cap_destroy_entry(nvlink_caps.fabric_mgmt);
|
||||
nvlink_caps.fabric_mgmt = NULL;
|
||||
}
|
||||
|
||||
if (nvlink_caps.root != NULL)
|
||||
{
|
||||
nv_cap_destroy_entry(nvlink_caps.root);
|
||||
nvlink_caps.root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int nvlink_cap_init(const char *path)
|
||||
{
|
||||
if (path == NULL)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "Invalid path: %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvlink_caps.root = nv_cap_init(path);
|
||||
if (nvlink_caps.root == NULL)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "Failed to initialize capabilities\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvlink_caps.fabric_mgmt = nv_cap_create_file_entry(nvlink_caps.root,
|
||||
NVLINK_CAP_FABRIC_MGMT,
|
||||
S_IRUSR);
|
||||
if (nvlink_caps.fabric_mgmt == NULL)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "Failed to create fabric-mgmt entry\n");
|
||||
nvlink_cap_exit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_CAPS_H_
|
||||
#define _NVLINK_CAPS_H_
|
||||
|
||||
/* List of supported capability type */
|
||||
#define NVLINK_CAP_FABRIC_MANAGEMENT 0
|
||||
|
||||
/* Max supported capabilities count */
|
||||
#define NVLINK_CAP_COUNT 1
|
||||
|
||||
int nvlink_cap_init(const char *path);
|
||||
void nvlink_cap_exit(void);
|
||||
int nvlink_cap_acquire(int fd, NvU32 type);
|
||||
void nvlink_cap_release(int fd);
|
||||
|
||||
#endif //_NVLINK_CAPS_H_
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_COMMON_H_
|
||||
#define _NVLINK_COMMON_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nvtypes.h"
|
||||
#include "nvCpuUuid.h"
|
||||
#include "nvlink_errors.h"
|
||||
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
// nvlink pci bar information
|
||||
struct nvlink_pci_bar_info
|
||||
{
|
||||
NvU64 busAddress;
|
||||
NvU64 baseAddr;
|
||||
NvU64 barSize;
|
||||
NvU32 offset;
|
||||
void *pBar;
|
||||
};
|
||||
|
||||
#define MAX_NVLINK_BARS 2
|
||||
|
||||
// nvlink pci information
|
||||
struct nvlink_pci_info
|
||||
{
|
||||
NvU32 domain;
|
||||
NvU8 bus;
|
||||
NvU8 device;
|
||||
NvU8 function;
|
||||
NvU32 pciDeviceId;
|
||||
NvU32 irq;
|
||||
NvBool intHooked;
|
||||
struct nvlink_pci_bar_info bars[MAX_NVLINK_BARS];
|
||||
};
|
||||
|
||||
// nvlink detailed device information
|
||||
struct nvlink_detailed_device_info
|
||||
{
|
||||
char *deviceName;
|
||||
NvU64 deviceType;
|
||||
NvU8 *devUuid;
|
||||
NvBool bInitialized;
|
||||
NvBool bEnableALI;
|
||||
void *dev_info; // Endpoint driver device info opaque
|
||||
// to core lib. Passed from end point
|
||||
// driver to core
|
||||
|
||||
struct nvlink_pci_info *pciInfo;
|
||||
};
|
||||
|
||||
// nvlink device registration parameters
|
||||
struct nvlink_device_register_params
|
||||
{
|
||||
//
|
||||
// Core lib device info opaque to endpoint driver
|
||||
// Passed from core lib to endpoint driver
|
||||
//
|
||||
void **deviceHandle;
|
||||
char *driverName;
|
||||
|
||||
struct nvlink_detailed_device_info *device_params;
|
||||
};
|
||||
|
||||
// nvlink detailed link information
|
||||
struct nvlink_detailed_link_info
|
||||
{
|
||||
void *deviceHandle; // Core library device handle passed
|
||||
// to endpoint driver during device
|
||||
// registration
|
||||
|
||||
void *link_info; // End point driver link info opaque
|
||||
// to core lib. Passed from end point
|
||||
// driver to core
|
||||
|
||||
char *linkName;
|
||||
NvU32 linkNumber;
|
||||
NvU32 version;
|
||||
NvBool bAcCoupled;
|
||||
const void *link_handlers;
|
||||
};
|
||||
|
||||
// nvlink link registration parameters
|
||||
struct nvlink_link_register_params
|
||||
{
|
||||
//
|
||||
// Core lib link info opaque to endpoint driver
|
||||
// Passed from core lib to endpoint driver
|
||||
//
|
||||
void **linkHandle;
|
||||
|
||||
struct nvlink_detailed_link_info *link_params;
|
||||
};
|
||||
|
||||
// nvlink client device handle
|
||||
struct nvlink_device_handle
|
||||
{
|
||||
NvU32 linkMask;
|
||||
struct nvlink_pci_info pciInfo;
|
||||
};
|
||||
|
||||
#define NVLINK_PCI_DEV_FMT "%04x:%02x:%02x.%x"
|
||||
#define NVLINK_PCI_DEV_FMT_ARGS(info) (info)->domain, \
|
||||
(info)->bus, \
|
||||
(info)->device, \
|
||||
(info)->function
|
||||
|
||||
// nvlink connection information
|
||||
struct nvlink_conn_info
|
||||
{
|
||||
NvU32 domain;
|
||||
NvU16 bus;
|
||||
NvU16 device;
|
||||
NvU16 function;
|
||||
NvU32 pciDeviceId;
|
||||
NvU8 devUuid[NV_UUID_LEN];
|
||||
NvU64 deviceType;
|
||||
NvU32 linkNumber;
|
||||
NvBool bConnected;
|
||||
NvU64 chipSid;
|
||||
};
|
||||
|
||||
// nvlink ioctrl params
|
||||
struct nvlink_ioctrl_params
|
||||
{
|
||||
void *osPrivate;
|
||||
NvU32 cmd;
|
||||
void *buf;
|
||||
NvU32 size;
|
||||
};
|
||||
|
||||
// Typedefs
|
||||
typedef struct nvlink_pci_bar_info nvlink_pci_bar_info;
|
||||
typedef struct nvlink_pci_info nvlink_pci_info;
|
||||
typedef struct nvlink_detailed_device_info nvlink_detailed_device_info;
|
||||
typedef struct nvlink_detailed_link_info nvlink_detailed_link_info;
|
||||
typedef struct nvlink_device_register_params nvlink_device_register_params;
|
||||
typedef struct nvlink_link_register_params nvlink_link_register_params;
|
||||
typedef struct nvlink_conn_info nvlink_conn_info;
|
||||
typedef struct nvlink_ioctrl_params nvlink_ioctrl_params;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_NVLINK_COMMON_H_
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015-2016 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_ERRORS_H_
|
||||
#define _NVLINK_ERRORS_H_
|
||||
|
||||
typedef int NvlStatus;
|
||||
|
||||
#define NVL_SUCCESS (NvlStatus) 0
|
||||
#define NVL_BAD_ARGS (NvlStatus) 1
|
||||
#define NVL_NO_MEM (NvlStatus) 2
|
||||
#define NVL_NOT_FOUND (NvlStatus) 3
|
||||
#define NVL_INITIALIZATION_PARTIAL_FAILURE (NvlStatus) 4
|
||||
#define NVL_INITIALIZATION_TOTAL_FAILURE (NvlStatus) 5
|
||||
#define NVL_PCI_ERROR (NvlStatus) 6
|
||||
#define NVL_ERR_GENERIC (NvlStatus) 7
|
||||
#define NVL_ERR_INVALID_STATE (NvlStatus) 8
|
||||
#define NVL_UNBOUND_DEVICE (NvlStatus) 9
|
||||
#define NVL_MORE_PROCESSING_REQUIRED (NvlStatus)10
|
||||
#define NVL_IO_ERROR (NvlStatus)11
|
||||
#define NVL_ERR_STATE_IN_USE (NvlStatus)12
|
||||
#define NVL_ERR_NOT_SUPPORTED (NvlStatus)13
|
||||
#define NVL_ERR_NOT_IMPLEMENTED (NvlStatus)14
|
||||
#define NVL_ERR_INSUFFICIENT_PERMISSIONS (NvlStatus)15
|
||||
#define NVL_ERR_OPERATING_SYSTEM (NvlStatus)16
|
||||
|
||||
#endif // _NVLINK_ERRORS_H_
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_EXPORT_H_
|
||||
#define _NVLINK_EXPORT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nvlink_common.h"
|
||||
|
||||
/*
|
||||
* Initializes core lib and does all that is needed
|
||||
* to access NVLINK functionality on the current platform.
|
||||
*/
|
||||
NvlStatus nvlink_lib_initialize(void);
|
||||
|
||||
/*
|
||||
* Frees any related resources and then unloads core lib.
|
||||
*/
|
||||
NvlStatus nvlink_lib_unload(void);
|
||||
|
||||
/*
|
||||
* Entry point for nvlink ioctl calls.
|
||||
*/
|
||||
NvlStatus nvlink_lib_ioctl_ctrl(nvlink_ioctrl_params *ctrl_params);
|
||||
|
||||
/*
|
||||
* Gets number of devices with type deviceType
|
||||
*/
|
||||
NvlStatus nvlink_lib_return_device_count_by_type(NvU32 deviceType, NvU32 *numDevices);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_NVLINK_EXPORT_H_
|
||||
@@ -0,0 +1,641 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "conftest.h"
|
||||
|
||||
#include "nvlink_os.h"
|
||||
#include "nvlink_linux.h"
|
||||
#include "nvlink_errors.h"
|
||||
#include "nvlink_export.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-procfs.h"
|
||||
#include "nv-time.h"
|
||||
#include "nvlink_caps.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define MAX_ERROR_STRING 512
|
||||
|
||||
typedef struct nvlink_file_private
|
||||
{
|
||||
struct
|
||||
{
|
||||
/* A duped file descriptor for fabric_mgmt capability */
|
||||
int fabric_mgmt;
|
||||
} capability_fds;
|
||||
} nvlink_file_private_t;
|
||||
|
||||
#define NVLINK_SET_FILE_PRIVATE(filp, data) ((filp)->private_data = (data))
|
||||
#define NVLINK_GET_FILE_PRIVATE(filp) ((nvlink_file_private_t *)(filp)->private_data)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct mutex lock;
|
||||
NvBool initialized;
|
||||
struct cdev cdev;
|
||||
dev_t devno;
|
||||
int opened;
|
||||
int major_devnum;
|
||||
} _nvlink_drvctx;
|
||||
|
||||
|
||||
// nvlink driver local state
|
||||
static _nvlink_drvctx nvlink_drvctx;
|
||||
|
||||
#if defined(CONFIG_PROC_FS)
|
||||
#define NV_DEFINE_SINGLE_NVLINK_PROCFS_FILE(name) \
|
||||
NV_DEFINE_SINGLE_PROCFS_FILE_READ_ONLY(name, nv_system_pm_lock)
|
||||
#endif
|
||||
|
||||
#define NVLINK_PROCFS_DIR "driver/nvidia-nvlink"
|
||||
|
||||
static struct proc_dir_entry *nvlink_procfs_dir = NULL;
|
||||
|
||||
#if defined(CONFIG_PROC_FS)
|
||||
static int nvlink_is_procfs_available = 1;
|
||||
#else
|
||||
static int nvlink_is_procfs_available = 0;
|
||||
#endif
|
||||
|
||||
static struct proc_dir_entry *nvlink_permissions = NULL;
|
||||
|
||||
static int nv_procfs_read_permissions(struct seq_file *s, void *v)
|
||||
{
|
||||
// Restrict device node permissions - 0666.
|
||||
seq_printf(s, "%s: %u\n", "DeviceFileMode", 438);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NV_DEFINE_SINGLE_NVLINK_PROCFS_FILE(permissions);
|
||||
|
||||
static void nvlink_permissions_exit(void)
|
||||
{
|
||||
if (!nvlink_permissions)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
proc_remove(nvlink_permissions);
|
||||
nvlink_permissions = NULL;
|
||||
}
|
||||
|
||||
static int nvlink_permissions_init(void)
|
||||
{
|
||||
if (!nvlink_procfs_dir)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
nvlink_permissions = NV_CREATE_PROC_FILE("permissions",
|
||||
nvlink_procfs_dir,
|
||||
permissions,
|
||||
NULL);
|
||||
if (!nvlink_permissions)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvlink_procfs_exit(void)
|
||||
{
|
||||
nvlink_permissions_exit();
|
||||
|
||||
if (!nvlink_procfs_dir)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
proc_remove(nvlink_procfs_dir);
|
||||
nvlink_procfs_dir = NULL;
|
||||
}
|
||||
|
||||
static int nvlink_procfs_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!nvlink_is_procfs_available)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
nvlink_procfs_dir = NV_CREATE_PROC_DIR(NVLINK_PROCFS_DIR, NULL);
|
||||
if (!nvlink_procfs_dir)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
rc = nvlink_permissions_init();
|
||||
if (rc < 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
|
||||
nvlink_procfs_exit();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int nvlink_fops_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int rc = 0;
|
||||
nvlink_file_private_t *private = NULL;
|
||||
|
||||
nvlink_print(NVLINK_DBG_INFO, "nvlink driver open\n");
|
||||
|
||||
mutex_lock(&nvlink_drvctx.lock);
|
||||
|
||||
// nvlink lib driver is currently exclusive open.
|
||||
if (nvlink_drvctx.opened)
|
||||
{
|
||||
rc = -EBUSY;
|
||||
goto open_error;
|
||||
}
|
||||
|
||||
private = (nvlink_file_private_t *)nvlink_malloc(sizeof(*private));
|
||||
if (private == NULL)
|
||||
{
|
||||
rc = -ENOMEM;
|
||||
goto open_error;
|
||||
}
|
||||
|
||||
private->capability_fds.fabric_mgmt = -1;
|
||||
NVLINK_SET_FILE_PRIVATE(filp, private);
|
||||
|
||||
// mark our state as opened
|
||||
nvlink_drvctx.opened = NV_TRUE;
|
||||
|
||||
open_error:
|
||||
mutex_unlock(&nvlink_drvctx.lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int nvlink_fops_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
nvlink_file_private_t *private = NVLINK_GET_FILE_PRIVATE(filp);
|
||||
|
||||
nvlink_print(NVLINK_DBG_INFO, "nvlink driver close\n");
|
||||
|
||||
if (private == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&nvlink_drvctx.lock);
|
||||
|
||||
if (private->capability_fds.fabric_mgmt > 0)
|
||||
{
|
||||
nvlink_cap_release(private->capability_fds.fabric_mgmt);
|
||||
private->capability_fds.fabric_mgmt = -1;
|
||||
}
|
||||
|
||||
nvlink_free(filp->private_data);
|
||||
NVLINK_SET_FILE_PRIVATE(filp, NULL);
|
||||
|
||||
// mark the device as not opened
|
||||
nvlink_drvctx.opened = NV_FALSE;
|
||||
|
||||
mutex_unlock(&nvlink_drvctx.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvlink_fops_ioctl(struct inode *inode,
|
||||
struct file *filp,
|
||||
unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
nvlink_ioctrl_params ctrl_params = {0};
|
||||
int param_size = _IOC_SIZE(cmd);
|
||||
void *param_buf = NULL;
|
||||
NvlStatus ret_val = 0;
|
||||
int rc = 0;
|
||||
|
||||
// no buffer for simple _IO types
|
||||
if (param_size)
|
||||
{
|
||||
// allocate a buffer to hold user input
|
||||
param_buf = kzalloc(param_size, GFP_KERNEL);
|
||||
if (NULL == param_buf)
|
||||
{
|
||||
rc = -ENOMEM;
|
||||
goto nvlink_ioctl_fail;
|
||||
}
|
||||
|
||||
// copy user input to kernel buffers. Simple _IOR() ioctls can skip this step.
|
||||
if (_IOC_DIR(cmd) & _IOC_WRITE)
|
||||
{
|
||||
// copy user input to local buffer
|
||||
if (copy_from_user(param_buf, (const void *)arg, param_size))
|
||||
{
|
||||
rc = -EFAULT;
|
||||
goto nvlink_ioctl_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctrl_params.osPrivate = filp->private_data;
|
||||
ctrl_params.cmd = _IOC_NR(cmd);
|
||||
ctrl_params.buf = param_buf;
|
||||
ctrl_params.size = param_size;
|
||||
|
||||
ret_val = nvlink_lib_ioctl_ctrl(&ctrl_params);
|
||||
if (NVL_SUCCESS != ret_val)
|
||||
{
|
||||
rc = -EINVAL;
|
||||
goto nvlink_ioctl_fail;
|
||||
}
|
||||
|
||||
// no copy for write-only ioctl
|
||||
if ((param_size) && (_IOC_DIR(cmd) & _IOC_READ))
|
||||
{
|
||||
if (copy_to_user((void *)arg, ctrl_params.buf, ctrl_params.size))
|
||||
{
|
||||
rc = -EFAULT;
|
||||
goto nvlink_ioctl_fail;
|
||||
}
|
||||
}
|
||||
|
||||
nvlink_ioctl_fail:
|
||||
if (param_buf)
|
||||
{
|
||||
kfree(param_buf);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define NV_FILE_INODE(file) (file)->f_inode
|
||||
|
||||
static long nvlink_fops_unlocked_ioctl(struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
return nvlink_fops_ioctl(NV_FILE_INODE(file), file, cmd, arg);
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations nvlink_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = nvlink_fops_open,
|
||||
.release = nvlink_fops_release,
|
||||
.unlocked_ioctl = nvlink_fops_unlocked_ioctl,
|
||||
};
|
||||
|
||||
int __init nvlink_core_init(void)
|
||||
{
|
||||
NvlStatus ret_val;
|
||||
int rc;
|
||||
|
||||
if (NV_TRUE == nvlink_drvctx.initialized)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "nvlink core interface already initialized\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mutex_init(&nvlink_drvctx.lock);
|
||||
|
||||
ret_val = nvlink_lib_initialize();
|
||||
if (NVL_SUCCESS != ret_val)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "Failed to initialize driver : %d\n", ret_val);
|
||||
rc = -ENODEV;
|
||||
goto nvlink_lib_initialize_fail;
|
||||
}
|
||||
|
||||
rc = alloc_chrdev_region(&nvlink_drvctx.devno, 0, NVLINK_NUM_MINOR_DEVICES,
|
||||
NVLINK_DEVICE_NAME);
|
||||
if (rc < 0)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "alloc_chrdev_region failed: %d\n", rc);
|
||||
goto alloc_chrdev_region_fail;
|
||||
}
|
||||
|
||||
nvlink_drvctx.major_devnum = MAJOR(nvlink_drvctx.devno);
|
||||
nvlink_print(NVLINK_DBG_INFO, "Nvlink Core is being initialized, major device number %d\n",
|
||||
nvlink_drvctx.major_devnum);
|
||||
|
||||
cdev_init(&nvlink_drvctx.cdev, &nvlink_fops);
|
||||
nvlink_drvctx.cdev.owner = THIS_MODULE;
|
||||
rc = cdev_add(&nvlink_drvctx.cdev, nvlink_drvctx.devno, NVLINK_NUM_MINOR_DEVICES);
|
||||
if (rc < 0)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, " Unable to create cdev\n");
|
||||
goto cdev_add_fail;
|
||||
}
|
||||
|
||||
rc = nvlink_procfs_init();
|
||||
if (rc < 0)
|
||||
{
|
||||
goto procfs_init_fail;
|
||||
}
|
||||
|
||||
rc = nvlink_cap_init(NVLINK_PROCFS_DIR);
|
||||
if (rc < 0)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, " Unable to create capability\n");
|
||||
goto cap_init_fail;
|
||||
}
|
||||
|
||||
nvlink_drvctx.initialized = NV_TRUE;
|
||||
|
||||
return 0;
|
||||
|
||||
cap_init_fail:
|
||||
nvlink_procfs_exit();
|
||||
|
||||
procfs_init_fail:
|
||||
cdev_del(&nvlink_drvctx.cdev);
|
||||
|
||||
cdev_add_fail:
|
||||
unregister_chrdev_region(nvlink_drvctx.devno, NVLINK_NUM_MINOR_DEVICES);
|
||||
|
||||
alloc_chrdev_region_fail:
|
||||
nvlink_lib_unload();
|
||||
|
||||
nvlink_lib_initialize_fail:
|
||||
nv_mutex_destroy(&nvlink_drvctx.lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void nvlink_core_exit(void)
|
||||
{
|
||||
if (NV_FALSE == nvlink_drvctx.initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nvlink_cap_exit();
|
||||
|
||||
nvlink_procfs_exit();
|
||||
|
||||
cdev_del(&nvlink_drvctx.cdev);
|
||||
|
||||
unregister_chrdev_region(nvlink_drvctx.devno, NVLINK_NUM_MINOR_DEVICES);
|
||||
|
||||
nvlink_lib_unload();
|
||||
|
||||
nv_mutex_destroy(&nvlink_drvctx.lock);
|
||||
|
||||
nvlink_print(NVLINK_DBG_INFO, "Unregistered Nvlink Core, major device number %d\n",
|
||||
nvlink_drvctx.major_devnum);
|
||||
}
|
||||
|
||||
void
|
||||
nvlink_print
|
||||
(
|
||||
const char *file,
|
||||
int line,
|
||||
const char *function,
|
||||
int log_level,
|
||||
const char *fmt,
|
||||
...
|
||||
)
|
||||
{
|
||||
va_list arglist;
|
||||
char nv_string[MAX_ERROR_STRING];
|
||||
char *sys_log_level;
|
||||
|
||||
switch (log_level) {
|
||||
case NVLINK_DBG_LEVEL_INFO:
|
||||
sys_log_level = KERN_INFO;
|
||||
break;
|
||||
case NVLINK_DBG_LEVEL_SETUP:
|
||||
sys_log_level = KERN_DEBUG;
|
||||
break;
|
||||
case NVLINK_DBG_LEVEL_USERERRORS:
|
||||
sys_log_level = KERN_NOTICE;
|
||||
break;
|
||||
case NVLINK_DBG_LEVEL_WARNINGS:
|
||||
sys_log_level = KERN_WARNING;
|
||||
break;
|
||||
case NVLINK_DBG_LEVEL_ERRORS:
|
||||
sys_log_level = KERN_ERR;
|
||||
break;
|
||||
default:
|
||||
sys_log_level = KERN_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
va_start(arglist, fmt);
|
||||
vsnprintf(nv_string, sizeof(nv_string), fmt, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
nv_string[sizeof(nv_string) - 1] = '\0';
|
||||
printk("%snvidia-nvlink: %s", sys_log_level, nv_string);
|
||||
}
|
||||
|
||||
void * nvlink_malloc(NvLength size)
|
||||
{
|
||||
return kmalloc(size, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void nvlink_free(void *ptr)
|
||||
{
|
||||
return kfree(ptr);
|
||||
}
|
||||
|
||||
char * nvlink_strcpy(char *dest, const char *src)
|
||||
{
|
||||
return strcpy(dest, src);
|
||||
}
|
||||
|
||||
int nvlink_strcmp(const char *dest, const char *src)
|
||||
{
|
||||
return strcmp(dest, src);
|
||||
}
|
||||
|
||||
NvLength nvlink_strlen(const char *s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
int nvlink_snprintf(char *dest, NvLength size, const char *fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
int chars_written;
|
||||
|
||||
va_start(arglist, fmt);
|
||||
chars_written = vsnprintf(dest, size, fmt, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
return chars_written;
|
||||
}
|
||||
|
||||
NvU32 nvlink_memRd32(const volatile void * address)
|
||||
{
|
||||
return (*(const volatile NvU32*)(address));
|
||||
}
|
||||
|
||||
void nvlink_memWr32(volatile void *address, NvU32 data)
|
||||
{
|
||||
(*(volatile NvU32 *)(address)) = data;
|
||||
}
|
||||
|
||||
NvU64 nvlink_memRd64(const volatile void * address)
|
||||
{
|
||||
return (*(const volatile NvU64 *)(address));
|
||||
}
|
||||
|
||||
void nvlink_memWr64(volatile void *address, NvU64 data)
|
||||
{
|
||||
(*(volatile NvU64 *)(address)) = data;
|
||||
}
|
||||
|
||||
void * nvlink_memset(void *dest, int value, NvLength size)
|
||||
{
|
||||
return memset(dest, value, size);
|
||||
}
|
||||
|
||||
void * nvlink_memcpy(void *dest, const void *src, NvLength size)
|
||||
{
|
||||
return memcpy(dest, src, size);
|
||||
}
|
||||
|
||||
int nvlink_memcmp(const void *s1, const void *s2, NvLength size)
|
||||
{
|
||||
return memcmp(s1, s2, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sleep for specified milliseconds. Yields the CPU to scheduler.
|
||||
*/
|
||||
void nvlink_sleep(unsigned int ms)
|
||||
{
|
||||
NV_STATUS status;
|
||||
|
||||
status = nv_sleep_ms(ms);
|
||||
|
||||
if (status != NV_OK)
|
||||
{
|
||||
if (printk_ratelimit())
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "NVLink: requested sleep duration"
|
||||
" %d msec exceeded %d msec\n",
|
||||
ms, NV_MAX_ISR_DELAY_MS);
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nvlink_assert(int cond)
|
||||
{
|
||||
if ((cond) == 0x0)
|
||||
{
|
||||
if (printk_ratelimit())
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "NVLink: Assertion failed!\n");
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
dbg_breakpoint();
|
||||
}
|
||||
}
|
||||
|
||||
void * nvlink_allocLock(void)
|
||||
{
|
||||
struct semaphore *sema;
|
||||
|
||||
sema = nvlink_malloc(sizeof(*sema));
|
||||
if (sema == NULL)
|
||||
{
|
||||
nvlink_print(NVLINK_DBG_ERRORS, "Failed to allocate sema!\n");
|
||||
return NULL;
|
||||
}
|
||||
sema_init(sema, 1);
|
||||
|
||||
return sema;
|
||||
}
|
||||
|
||||
void nvlink_acquireLock(void *hLock)
|
||||
{
|
||||
down(hLock);
|
||||
}
|
||||
|
||||
void nvlink_releaseLock(void *hLock)
|
||||
{
|
||||
up(hLock);
|
||||
}
|
||||
|
||||
void nvlink_freeLock(void *hLock)
|
||||
{
|
||||
if (NULL == hLock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NVLINK_FREE(hLock);
|
||||
}
|
||||
|
||||
NvBool nvlink_isLockOwner(void *hLock)
|
||||
{
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
NvlStatus nvlink_acquire_fabric_mgmt_cap(void *osPrivate, NvU64 capDescriptor)
|
||||
{
|
||||
int dup_fd = -1;
|
||||
nvlink_file_private_t *private_data = (nvlink_file_private_t *)osPrivate;
|
||||
|
||||
if (private_data == NULL)
|
||||
{
|
||||
return NVL_BAD_ARGS;
|
||||
}
|
||||
|
||||
dup_fd = nvlink_cap_acquire((int)capDescriptor,
|
||||
NVLINK_CAP_FABRIC_MANAGEMENT);
|
||||
if (dup_fd < 0)
|
||||
{
|
||||
return NVL_ERR_OPERATING_SYSTEM;
|
||||
}
|
||||
|
||||
private_data->capability_fds.fabric_mgmt = dup_fd;
|
||||
return NVL_SUCCESS;
|
||||
}
|
||||
|
||||
int nvlink_is_fabric_manager(void *osPrivate)
|
||||
{
|
||||
nvlink_file_private_t *private_data = (nvlink_file_private_t *)osPrivate;
|
||||
|
||||
/* Make sure that fabric mgmt capbaility fd is valid */
|
||||
if ((private_data == NULL) ||
|
||||
(private_data->capability_fds.fabric_mgmt < 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nvlink_is_admin(void)
|
||||
{
|
||||
return NV_IS_SUSER();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2014 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_LINUX_H_
|
||||
#define _NVLINK_LINUX_H_
|
||||
|
||||
#include <linux/init.h> // for entry/exit macros
|
||||
#include <linux/sched.h> // for "struct task_struct"
|
||||
#include <linux/kernel.h> // for printk priority macros
|
||||
#include <linux/fs.h>
|
||||
|
||||
|
||||
#define NVLINK_DEVICE_NAME "nvidia-nvlink"
|
||||
#define NVLINK_NUM_MINOR_DEVICES 1
|
||||
|
||||
/*
|
||||
* @Brief : Debug Breakpoint implementation
|
||||
*
|
||||
* @Description :
|
||||
*
|
||||
* @returns void
|
||||
*/
|
||||
static inline void
|
||||
dbg_breakpoint(void)
|
||||
{
|
||||
/* OS specific breakpoint implemented for NVLink library */
|
||||
#if defined(DEBUG)
|
||||
#if defined(CONFIG_X86_REMOTE_DEBUG) || defined(CONFIG_KGDB) || defined(CONFIG_XMON)
|
||||
#if defined(NVCPU_X86) || defined(NVCPU_X86_64)
|
||||
__asm__ __volatile__ ("int $3");
|
||||
#elif defined(NVCPU_ARM)
|
||||
__asm__ __volatile__ (".word %c0" :: "i" (KGDB_COMPILED_BREAK));
|
||||
#elif defined(NVCPU_AARCH64)
|
||||
# warning "Need to implement dbg_breakpoint() for aarch64"
|
||||
#elif defined(NVCPU_PPC64LE)
|
||||
__asm__ __volatile__ ("trap");
|
||||
#endif /* NVCPU_X86 || NVCPU_X86_64 */
|
||||
#elif defined(CONFIG_KDB)
|
||||
KDB_ENTER();
|
||||
#endif /* CONFIG_X86_REMOTE_DEBUG || CONFIG_KGDB || CONFIG_XMON */
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
#endif //_NVLINK_LINUX_H_
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_OS_H_
|
||||
#define _NVLINK_OS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nvlink_common.h"
|
||||
|
||||
#define TOP_LEVEL_LOCKING_DISABLED 1
|
||||
#define PER_LINK_LOCKING_DISABLED 1
|
||||
|
||||
#define NVLINK_FREE(x) nvlink_free((void *)x)
|
||||
|
||||
// Memory management functions
|
||||
void * nvlink_malloc(NvLength);
|
||||
void nvlink_free(void *);
|
||||
void * nvlink_memset(void *, int, NvLength);
|
||||
void * nvlink_memcpy(void *, const void *, NvLength);
|
||||
int nvlink_memcmp(const void *, const void *, NvLength);
|
||||
NvU32 nvlink_memRd32(const volatile void *);
|
||||
void nvlink_memWr32(volatile void *, NvU32);
|
||||
NvU64 nvlink_memRd64(const volatile void *);
|
||||
void nvlink_memWr64(volatile void *, NvU64);
|
||||
|
||||
// String management functions
|
||||
char * nvlink_strcpy(char *, const char *);
|
||||
NvLength nvlink_strlen(const char *);
|
||||
int nvlink_strcmp(const char *, const char *);
|
||||
int nvlink_snprintf(char *, NvLength, const char *, ...);
|
||||
|
||||
// Locking support functions
|
||||
void * nvlink_allocLock(void);
|
||||
void nvlink_acquireLock(void *);
|
||||
NvBool nvlink_isLockOwner(void *);
|
||||
void nvlink_releaseLock(void *);
|
||||
void nvlink_freeLock(void *);
|
||||
|
||||
// Miscellaneous functions
|
||||
void nvlink_assert(int expression);
|
||||
void nvlink_sleep(unsigned int ms);
|
||||
void nvlink_print(const char *, int, const char *, int, const char *, ...);
|
||||
int nvlink_is_admin(void);
|
||||
|
||||
// Capability functions
|
||||
NvlStatus nvlink_acquire_fabric_mgmt_cap(void *osPrivate, NvU64 capDescriptor);
|
||||
int nvlink_is_fabric_manager(void *osPrivate);
|
||||
|
||||
#define NVLINK_DBG_LEVEL_INFO 0x0
|
||||
#define NVLINK_DBG_LEVEL_SETUP 0x1
|
||||
#define NVLINK_DBG_LEVEL_USERERRORS 0x2
|
||||
#define NVLINK_DBG_LEVEL_WARNINGS 0x3
|
||||
#define NVLINK_DBG_LEVEL_ERRORS 0x4
|
||||
|
||||
#define NVLINK_DBG_WHERE __FILE__, __LINE__, __FUNCTION__
|
||||
#define NVLINK_DBG_INFO NVLINK_DBG_WHERE, NVLINK_DBG_LEVEL_INFO
|
||||
#define NVLINK_DBG_SETUP NVLINK_DBG_WHERE, NVLINK_DBG_LEVEL_SETUP
|
||||
#define NVLINK_DBG_USERERRORS NVLINK_DBG_WHERE, NVLINK_DBG_LEVEL_USERERRORS
|
||||
#define NVLINK_DBG_WARNINGS NVLINK_DBG_WHERE, NVLINK_DBG_LEVEL_WARNINGS
|
||||
#define NVLINK_DBG_ERRORS NVLINK_DBG_WHERE, NVLINK_DBG_LEVEL_ERRORS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_NVLINK_OS_H_
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_PCI_H_
|
||||
#define _NVLINK_PCI_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include "nvlink_common.h"
|
||||
|
||||
#define NV_PCI_RESOURCE_START(dev, bar) pci_resource_start(dev, (bar))
|
||||
#define NV_PCI_RESOURCE_SIZE(dev, bar) pci_resource_len(dev, (bar))
|
||||
#define NV_PCI_RESOURCE_FLAGS(dev, bar) pci_resource_flags(dev, (bar))
|
||||
|
||||
#if defined(NVCPU_X86)
|
||||
#define NV_PCI_RESOURCE_VALID(dev, bar) \
|
||||
((NV_PCI_RESOURCE_START(dev, bar) != 0) && \
|
||||
(NV_PCI_RESOURCE_SIZE(dev, bar) != 0) && \
|
||||
(!((NV_PCI_RESOURCE_FLAGS(dev, bar) & PCI_BASE_ADDRESS_MEM_TYPE_64) && \
|
||||
((NV_PCI_RESOURCE_START(dev, bar) >> PAGE_SHIFT) > 0xfffffULL))))
|
||||
#else
|
||||
#define NV_PCI_RESOURCE_VALID(dev, bar) \
|
||||
((NV_PCI_RESOURCE_START(dev, bar) != 0) && \
|
||||
(NV_PCI_RESOURCE_SIZE(dev, bar) != 0))
|
||||
#endif
|
||||
|
||||
#define NV_PCI_DOMAIN_NUMBER(dev) (NvU32)pci_domain_nr(dev->bus)
|
||||
#define NV_PCI_BUS_NUMBER(dev) (dev)->bus->number
|
||||
#define NV_PCI_DEVFN(dev) (dev)->devfn
|
||||
#define NV_PCI_SLOT_NUMBER(dev) PCI_SLOT(NV_PCI_DEVFN(dev))
|
||||
|
||||
#define NV_PCI_DEV_FMT NVLINK_PCI_DEV_FMT
|
||||
#define NV_PCI_DEV_FMT_ARGS(dev) \
|
||||
NV_PCI_DOMAIN_NUMBER(dev), NV_PCI_BUS_NUMBER(dev), \
|
||||
NV_PCI_SLOT_NUMBER(dev), PCI_FUNC((dev)->devfn)
|
||||
|
||||
#define NVRM_PCICFG_NUM_BARS 6
|
||||
#define NVRM_PCICFG_BAR_OFFSET(i) (0x10 + (i) * 4)
|
||||
|
||||
#define NV_PCIE_CFG_MAX_OFFSET 0x1000
|
||||
|
||||
#endif // _NVLINK_PCI_H_
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015-2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _NVLINK_PROTO_H_
|
||||
#define _NVLINK_PROTO_H_
|
||||
|
||||
#include "nvlink_common.h"
|
||||
|
||||
/*
|
||||
* Functions defined in nvlink_linux.c
|
||||
*/
|
||||
|
||||
int nvlink_core_init (void);
|
||||
void nvlink_core_exit (void);
|
||||
|
||||
/*
|
||||
* Functions defined in nvswitch_linux.c
|
||||
*/
|
||||
int nvswitch_init (void);
|
||||
void nvswitch_exit (void);
|
||||
|
||||
#if defined(NVCPU_AARCH64)
|
||||
/*
|
||||
* Functions defined in tegrashim_linux.c (Tegra only)
|
||||
*/
|
||||
int tegrashim_init (void);
|
||||
void tegrashim_exit (void);
|
||||
NvlStatus tegrashim_init_device (struct pci_dev *);
|
||||
#endif
|
||||
|
||||
#endif /* _NVLINK_PROTO_H_ */
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
bool libspdm_aead_gcm_prealloc(void **context);
|
||||
void libspdm_aead_free(void *context);
|
||||
bool libspdm_aead_aes_gcm_encrypt_prealloc(void *context,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
uint8_t *tag_out, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size);
|
||||
bool libspdm_aead_aes_gcm_decrypt_prealloc(void *context,
|
||||
const uint8_t *key, size_t key_size,
|
||||
const uint8_t *iv, size_t iv_size,
|
||||
const uint8_t *a_data, size_t a_data_size,
|
||||
const uint8_t *data_in, size_t data_in_size,
|
||||
const uint8_t *tag, size_t tag_size,
|
||||
uint8_t *data_out, size_t *data_out_size);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
static inline int nv_follow_pfn(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
unsigned long *pfn)
|
||||
{
|
||||
#if defined(NV_UNSAFE_FOLLOW_PFN_PRESENT)
|
||||
return unsafe_follow_pfn(vma, address, pfn);
|
||||
#else
|
||||
return follow_pfn(vma, address, pfn);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Locates the PFNs for a user IO address range, and converts those to
|
||||
* their associated PTEs.
|
||||
*
|
||||
* @param[in] vma VMA that contains the virtual address range given by the
|
||||
* start and page count parameters.
|
||||
* @param[in] start Beginning of the virtual address range of the IO PTEs.
|
||||
* @param[in] page_count Number of pages containing the IO range being
|
||||
* mapped.
|
||||
* @param[in,out] pte_array Storage array for PTE addresses. Must be large
|
||||
* enough to contain at least page_count pointers.
|
||||
*
|
||||
* @return NV_OK if the PTEs were identified successfully, error otherwise.
|
||||
*/
|
||||
static NV_STATUS get_io_ptes(struct vm_area_struct *vma,
|
||||
NvUPtr start,
|
||||
NvU64 page_count,
|
||||
NvU64 **pte_array)
|
||||
{
|
||||
NvU64 i;
|
||||
unsigned long pfn;
|
||||
|
||||
for (i = 0; i < page_count; i++)
|
||||
{
|
||||
if (nv_follow_pfn(vma, (start + (i * PAGE_SIZE)), &pfn) < 0)
|
||||
{
|
||||
return NV_ERR_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
pte_array[i] = (NvU64 *)(pfn << PAGE_SHIFT);
|
||||
|
||||
if (i == 0)
|
||||
continue;
|
||||
|
||||
//
|
||||
// This interface is to be used for contiguous, uncacheable I/O regions.
|
||||
// Internally, osCreateOsDescriptorFromIoMemory() checks the user-provided
|
||||
// flags against this, and creates a single memory descriptor with the same
|
||||
// attributes. This check ensures the actual mapping supplied matches the
|
||||
// user's declaration. Ensure the PFNs represent a contiguous range,
|
||||
// error if they do not.
|
||||
//
|
||||
if ((NvU64)pte_array[i] != (((NvU64)pte_array[i-1]) + PAGE_SIZE))
|
||||
{
|
||||
return NV_ERR_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_lookup_user_io_memory(
|
||||
void *address,
|
||||
NvU64 page_count,
|
||||
NvU64 **pte_array
|
||||
)
|
||||
{
|
||||
NV_STATUS rmStatus;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long pfn;
|
||||
NvUPtr start = (NvUPtr)address;
|
||||
void **result_array;
|
||||
|
||||
if (!NV_MAY_SLEEP())
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s(): invalid context!\n", __FUNCTION__);
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
rmStatus = os_alloc_mem((void **)&result_array, (page_count * sizeof(NvP64)));
|
||||
if (rmStatus != NV_OK)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: failed to allocate page table!\n");
|
||||
return rmStatus;
|
||||
}
|
||||
|
||||
nv_mmap_read_lock(mm);
|
||||
|
||||
// find the first VMA which intersects the interval start_addr..end_addr-1,
|
||||
vma = find_vma_intersection(mm, start, start+1);
|
||||
|
||||
// Verify that the given address range is contained in a single vma
|
||||
if ((vma == NULL) || ((vma->vm_flags & (VM_IO | VM_PFNMAP)) == 0) ||
|
||||
!((vma->vm_start <= start) &&
|
||||
((vma->vm_end - start) >> PAGE_SHIFT >= page_count)))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"Cannot map memory with base addr 0x%llx and size of 0x%llx pages\n",
|
||||
start ,page_count);
|
||||
rmStatus = NV_ERR_INVALID_ADDRESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (nv_follow_pfn(vma, start, &pfn) < 0)
|
||||
{
|
||||
rmStatus = NV_ERR_INVALID_ADDRESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rmStatus = get_io_ptes(vma, start, page_count, (NvU64 **)result_array);
|
||||
if (rmStatus == NV_OK)
|
||||
*pte_array = (NvU64 *)result_array;
|
||||
|
||||
done:
|
||||
nv_mmap_read_unlock(mm);
|
||||
|
||||
if (rmStatus != NV_OK)
|
||||
{
|
||||
os_free_mem(result_array);
|
||||
}
|
||||
|
||||
return rmStatus;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_lock_user_pages(
|
||||
void *address,
|
||||
NvU64 page_count,
|
||||
void **page_array,
|
||||
NvU32 flags
|
||||
)
|
||||
{
|
||||
NV_STATUS rmStatus;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct page **user_pages;
|
||||
NvU64 i, pinned;
|
||||
unsigned int gup_flags = DRF_VAL(_LOCK_USER_PAGES, _FLAGS, _WRITE, flags) ? FOLL_WRITE : 0;
|
||||
int ret;
|
||||
|
||||
if (!NV_MAY_SLEEP())
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s(): invalid context!\n", __FUNCTION__);
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
rmStatus = os_alloc_mem((void **)&user_pages,
|
||||
(page_count * sizeof(*user_pages)));
|
||||
if (rmStatus != NV_OK)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: failed to allocate page table!\n");
|
||||
return rmStatus;
|
||||
}
|
||||
|
||||
nv_mmap_read_lock(mm);
|
||||
ret = NV_PIN_USER_PAGES((unsigned long)address,
|
||||
page_count, gup_flags, user_pages, NULL);
|
||||
nv_mmap_read_unlock(mm);
|
||||
pinned = ret;
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
os_free_mem(user_pages);
|
||||
return NV_ERR_INVALID_ADDRESS;
|
||||
}
|
||||
else if (pinned < page_count)
|
||||
{
|
||||
for (i = 0; i < pinned; i++)
|
||||
NV_UNPIN_USER_PAGE(user_pages[i]);
|
||||
os_free_mem(user_pages);
|
||||
return NV_ERR_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
*page_array = user_pages;
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_unlock_user_pages(
|
||||
NvU64 page_count,
|
||||
void *page_array
|
||||
)
|
||||
{
|
||||
NvBool write = 1;
|
||||
struct page **user_pages = page_array;
|
||||
NvU32 i;
|
||||
|
||||
for (i = 0; i < page_count; i++)
|
||||
{
|
||||
if (write)
|
||||
set_page_dirty_lock(user_pages[i]);
|
||||
NV_UNPIN_USER_PAGE(user_pages[i]);
|
||||
}
|
||||
|
||||
os_free_mem(user_pages);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
void* NV_API_CALL os_pci_init_handle(
|
||||
NvU32 domain,
|
||||
NvU8 bus,
|
||||
NvU8 slot,
|
||||
NvU8 function,
|
||||
NvU16 *vendor,
|
||||
NvU16 *device
|
||||
)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned int devfn = PCI_DEVFN(slot, function);
|
||||
|
||||
if (!NV_MAY_SLEEP())
|
||||
return NULL;
|
||||
|
||||
dev = NV_GET_DOMAIN_BUS_AND_SLOT(domain, bus, devfn);
|
||||
if (dev != NULL)
|
||||
{
|
||||
if (vendor) *vendor = dev->vendor;
|
||||
if (device) *device = dev->device;
|
||||
pci_dev_put(dev); /* TODO: Fix me! (hotplug) */
|
||||
}
|
||||
return (void *) dev;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_pci_read_byte(
|
||||
void *handle,
|
||||
NvU32 offset,
|
||||
NvU8 *pReturnValue
|
||||
)
|
||||
{
|
||||
if (offset >= NV_PCIE_CFG_MAX_OFFSET)
|
||||
{
|
||||
*pReturnValue = 0xff;
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
pci_read_config_byte( (struct pci_dev *) handle, offset, pReturnValue);
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_pci_read_word(
|
||||
void *handle,
|
||||
NvU32 offset,
|
||||
NvU16 *pReturnValue
|
||||
)
|
||||
{
|
||||
if (offset >= NV_PCIE_CFG_MAX_OFFSET)
|
||||
{
|
||||
*pReturnValue = 0xffff;
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
pci_read_config_word( (struct pci_dev *) handle, offset, pReturnValue);
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_pci_read_dword(
|
||||
void *handle,
|
||||
NvU32 offset,
|
||||
NvU32 *pReturnValue
|
||||
)
|
||||
{
|
||||
if (offset >= NV_PCIE_CFG_MAX_OFFSET)
|
||||
{
|
||||
*pReturnValue = 0xffffffff;
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
pci_read_config_dword( (struct pci_dev *) handle, offset, pReturnValue);
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_pci_write_byte(
|
||||
void *handle,
|
||||
NvU32 offset,
|
||||
NvU8 value
|
||||
)
|
||||
{
|
||||
if (offset >= NV_PCIE_CFG_MAX_OFFSET)
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
|
||||
pci_write_config_byte( (struct pci_dev *) handle, offset, value);
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_pci_write_word(
|
||||
void *handle,
|
||||
NvU32 offset,
|
||||
NvU16 value
|
||||
)
|
||||
{
|
||||
if (offset >= NV_PCIE_CFG_MAX_OFFSET)
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
|
||||
pci_write_config_word( (struct pci_dev *) handle, offset, value);
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_pci_write_dword(
|
||||
void *handle,
|
||||
NvU32 offset,
|
||||
NvU32 value
|
||||
)
|
||||
{
|
||||
if (offset >= NV_PCIE_CFG_MAX_OFFSET)
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
|
||||
pci_write_config_dword( (struct pci_dev *) handle, offset, value);
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NvBool NV_API_CALL os_pci_remove_supported(void)
|
||||
{
|
||||
#if defined NV_PCI_STOP_AND_REMOVE_BUS_DEVICE
|
||||
return NV_TRUE;
|
||||
#else
|
||||
return NV_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NV_API_CALL os_pci_remove(
|
||||
void *handle
|
||||
)
|
||||
{
|
||||
#if defined(NV_PCI_STOP_AND_REMOVE_BUS_DEVICE)
|
||||
NV_PCI_STOP_AND_REMOVE_BUS_DEVICE(handle);
|
||||
#elif defined(DEBUG)
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: %s() is called even though NV_PCI_STOP_AND_REMOVE_BUS_DEVICE is not defined\n",
|
||||
__FUNCTION__);
|
||||
os_dbg_breakpoint();
|
||||
#endif
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL
|
||||
os_enable_pci_req_atomics(
|
||||
void *handle,
|
||||
enum os_pci_req_atomics_type type
|
||||
)
|
||||
{
|
||||
#ifdef NV_PCI_ENABLE_ATOMIC_OPS_TO_ROOT_PRESENT
|
||||
int ret;
|
||||
u16 val;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OS_INTF_PCIE_REQ_ATOMICS_32BIT:
|
||||
ret = pci_enable_atomic_ops_to_root(handle,
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP32);
|
||||
break;
|
||||
case OS_INTF_PCIE_REQ_ATOMICS_64BIT:
|
||||
ret = pci_enable_atomic_ops_to_root(handle,
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP64);
|
||||
break;
|
||||
case OS_INTF_PCIE_REQ_ATOMICS_128BIT:
|
||||
ret = pci_enable_atomic_ops_to_root(handle,
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP128);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
/*
|
||||
* GPUs that don't support Requester Atomics have its
|
||||
* PCI_EXP_DEVCTL2_ATOMIC_REQ always set to 0 even after SW enables it.
|
||||
*/
|
||||
if ((pcie_capability_read_word(handle, PCI_EXP_DEVCTL2, &val) == 0) &&
|
||||
(val & PCI_EXP_DEVCTL2_ATOMIC_REQ))
|
||||
{
|
||||
return NV_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NV_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2000-2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#define NV_DEFINE_REGISTRY_KEY_TABLE
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
#include "nv-reg.h"
|
||||
#include "nv-gpu-info.h"
|
||||
|
||||
/*!
|
||||
* @brief This function parses the PCI BDF identifier string and returns the
|
||||
* Domain, Bus, Device and function components from the PCI BDF string.
|
||||
*
|
||||
* This parser is highly adaptable and hence allows PCI BDF string in following
|
||||
* 3 formats.
|
||||
*
|
||||
* 1) bus:slot : Domain and function defaults to 0.
|
||||
* 2) domain:bus:slot : Function defaults to 0.
|
||||
* 3) domain:bus:slot.func : Complete PCI dev id string.
|
||||
*
|
||||
* @param[in] pci_dev_str String containing the BDF to be parsed.
|
||||
* @param[out] pci_domain Pointer where pci_domain is to be returned.
|
||||
* @param[out] pci_bus Pointer where pci_bus is to be returned.
|
||||
* @param[out] pci_slot Pointer where pci_slot is to be returned.
|
||||
* @param[out] pci_func Pointer where pci_func is to be returned.
|
||||
*
|
||||
* @return NV_TRUE if succeeds, or NV_FALSE otherwise.
|
||||
*/
|
||||
static NV_STATUS pci_str_to_bdf(char *pci_dev_str, NvU32 *pci_domain,
|
||||
NvU32 *pci_bus, NvU32 *pci_slot, NvU32 *pci_func)
|
||||
{
|
||||
char *option_string = NULL;
|
||||
char *token, *string;
|
||||
NvU32 domain, bus, slot;
|
||||
NV_STATUS status = NV_OK;
|
||||
|
||||
//
|
||||
// remove_spaces() allocates memory, hence we need to keep a pointer
|
||||
// to the original string for freeing at end of function.
|
||||
//
|
||||
if ((option_string = rm_remove_spaces(pci_dev_str)) == NULL)
|
||||
{
|
||||
// memory allocation failed, returning
|
||||
return NV_ERR_GENERIC;
|
||||
}
|
||||
|
||||
string = option_string;
|
||||
|
||||
if (!strlen(string) || !pci_domain || !pci_bus || !pci_slot || !pci_func)
|
||||
{
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((token = strsep(&string, ".")) != NULL)
|
||||
{
|
||||
// PCI device can have maximum 8 functions only.
|
||||
if ((string != NULL) && (!(*string >= '0' && *string <= '7') ||
|
||||
(strlen(string) > 1)))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: Invalid PCI function in token %s\n",
|
||||
pci_dev_str);
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
else if (string == NULL)
|
||||
{
|
||||
*pci_func = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pci_func = (NvU32)(*string - '0');
|
||||
}
|
||||
|
||||
domain = simple_strtoul(token, &string, 16);
|
||||
|
||||
if ((string == NULL) || (*string != ':') || (*(string + 1) == '\0'))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: Invalid PCI domain/bus in token %s\n",
|
||||
pci_dev_str);
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
token = string;
|
||||
bus = simple_strtoul((token + 1), &string, 16);
|
||||
|
||||
if (string == NULL)
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: Invalid PCI bus/slot in token %s\n",
|
||||
pci_dev_str);
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*string != '\0')
|
||||
{
|
||||
if ((*string != ':') || (*(string + 1) == '\0'))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: Invalid PCI slot in token %s\n",
|
||||
pci_dev_str);
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
token = string;
|
||||
slot = (NvU32)simple_strtoul(token + 1, &string, 16);
|
||||
if ((slot == 0) && ((token + 1) == string))
|
||||
{
|
||||
nv_printf(NV_DBG_ERRORS,
|
||||
"NVRM: Invalid PCI slot in token %s\n",
|
||||
pci_dev_str);
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
*pci_domain = domain;
|
||||
*pci_bus = bus;
|
||||
*pci_slot = slot;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pci_slot = bus;
|
||||
*pci_bus = domain;
|
||||
*pci_domain = 0;
|
||||
}
|
||||
status = NV_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = NV_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
done:
|
||||
// Freeing the memory allocated by remove_spaces().
|
||||
os_free_mem(option_string);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This function parses the registry keys per GPU device. It accepts a
|
||||
* semicolon separated list of key=value pairs. The first key value pair MUST be
|
||||
* "pci=DDDD:BB:DD.F;" where DDDD is Domain, BB is Bus Id, DD is device slot
|
||||
* number and F is the Function. This PCI BDF is used to identify which GPU to
|
||||
* assign the registry keys that follows next.
|
||||
* If a GPU corresponding to the value specified in "pci=DDDD:BB:DD.F;" is NOT
|
||||
* found, then all the registry keys that follows are skipped, until we find next
|
||||
* valid pci identified "pci=DDDD:BB:DD.F;". Following are the valid formats for
|
||||
* the value of the "pci" string:
|
||||
* 1) bus:slot : Domain and function defaults to 0.
|
||||
* 2) domain:bus:slot : Function defaults to 0.
|
||||
* 3) domain:bus:slot.func : Complete PCI dev id string.
|
||||
*
|
||||
*
|
||||
* @param[in] sp pointer to nvidia_stack_t struct.
|
||||
*
|
||||
* @return NV_OK if succeeds, or NV_STATUS error code otherwise.
|
||||
*/
|
||||
NV_STATUS nv_parse_per_device_option_string(nvidia_stack_t *sp)
|
||||
{
|
||||
NV_STATUS status = NV_OK;
|
||||
char *option_string = NULL;
|
||||
char *ptr, *token;
|
||||
char *name, *value;
|
||||
NvU32 data, domain, bus, slot, func;
|
||||
nv_linux_state_t *nvl = NULL;
|
||||
nv_state_t *nv = NULL;
|
||||
|
||||
if (NVreg_RegistryDwordsPerDevice != NULL)
|
||||
{
|
||||
if ((option_string = rm_remove_spaces(NVreg_RegistryDwordsPerDevice)) == NULL)
|
||||
{
|
||||
return NV_ERR_GENERIC;
|
||||
}
|
||||
|
||||
ptr = option_string;
|
||||
|
||||
while ((token = strsep(&ptr, ";")) != NULL)
|
||||
{
|
||||
if (!(name = strsep(&token, "=")) || !strlen(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(value = strsep(&token, "=")) || !strlen(value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strsep(&token, "=") != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this key is "pci", then value is pci_dev id string
|
||||
// which needs special parsing as it is NOT a dword.
|
||||
if (strcmp(name, NV_REG_PCI_DEVICE_BDF) == 0)
|
||||
{
|
||||
status = pci_str_to_bdf(value, &domain, &bus, &slot, &func);
|
||||
|
||||
// Check if PCI_DEV id string was in a valid format or NOT.
|
||||
if (NV_OK != status)
|
||||
{
|
||||
// lets reset cached pci dev
|
||||
nv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvl = find_pci(domain, bus, slot, func);
|
||||
//
|
||||
// If NO GPU found corresponding to this GPU, then reset
|
||||
// cached state. This helps ignore the following registry
|
||||
// keys until valid PCI BDF is found in the commandline.
|
||||
//
|
||||
if (!nvl)
|
||||
{
|
||||
nv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
nv = NV_STATE_PTR(nvl);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if cached pci_dev string in the commandline is in valid
|
||||
// format, else we will skip all the successive registry entries
|
||||
// (<key, value> pairs) until a valid PCI_DEV string is encountered
|
||||
// in the commandline.
|
||||
//
|
||||
if (!nv)
|
||||
continue;
|
||||
|
||||
data = (NvU32)simple_strtoul(value, NULL, 0);
|
||||
|
||||
rm_write_registry_dword(sp, nv, name, data);
|
||||
}
|
||||
|
||||
os_free_mem(option_string);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare given string UUID with the GpuBlacklist or ExcludedGpus registry
|
||||
* parameter string and return whether the UUID is in the GPU exclusion list
|
||||
*/
|
||||
NvBool nv_is_uuid_in_gpu_exclusion_list(const char *uuid)
|
||||
{
|
||||
const char *input;
|
||||
char *list;
|
||||
char *ptr;
|
||||
char *token;
|
||||
|
||||
//
|
||||
// When both NVreg_GpuBlacklist and NVreg_ExcludedGpus are defined
|
||||
// NVreg_ExcludedGpus takes precedence.
|
||||
//
|
||||
if (NVreg_ExcludedGpus != NULL)
|
||||
input = NVreg_ExcludedGpus;
|
||||
else if (NVreg_GpuBlacklist != NULL)
|
||||
input = NVreg_GpuBlacklist;
|
||||
else
|
||||
return NV_FALSE;
|
||||
|
||||
if ((list = rm_remove_spaces(input)) == NULL)
|
||||
return NV_FALSE;
|
||||
|
||||
ptr = list;
|
||||
|
||||
while ((token = strsep(&ptr, ",")) != NULL)
|
||||
{
|
||||
if (strcmp(token, uuid) == 0)
|
||||
{
|
||||
os_free_mem(list);
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
os_free_mem(list);
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_registry_init(void)
|
||||
{
|
||||
nv_parm_t *entry;
|
||||
unsigned int i;
|
||||
nvidia_stack_t *sp = NULL;
|
||||
|
||||
if (nv_kmem_cache_alloc_stack(&sp) != 0)
|
||||
{
|
||||
return NV_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (NVreg_RmNvlinkBandwidth != NULL)
|
||||
{
|
||||
rm_write_registry_string(sp, NULL,
|
||||
"RmNvlinkBandwidth",
|
||||
NVreg_RmNvlinkBandwidth,
|
||||
strlen(NVreg_RmNvlinkBandwidth));
|
||||
}
|
||||
|
||||
if (NVreg_RmMsg != NULL)
|
||||
{
|
||||
rm_write_registry_string(sp, NULL,
|
||||
"RmMsg", NVreg_RmMsg, strlen(NVreg_RmMsg));
|
||||
}
|
||||
|
||||
rm_parse_option_string(sp, NVreg_RegistryDwords);
|
||||
|
||||
for (i = 0; (entry = &nv_parms[i])->name != NULL; i++)
|
||||
{
|
||||
rm_write_registry_dword(sp, NULL, entry->name, *entry->data);
|
||||
}
|
||||
|
||||
nv_kmem_cache_free_stack(sp);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1999-2011 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
||||
#include "os-interface.h"
|
||||
#include "nv-linux.h"
|
||||
|
||||
void* NV_API_CALL os_map_user_space(
|
||||
NvU64 start,
|
||||
NvU64 size_bytes,
|
||||
NvU32 mode,
|
||||
NvU32 protect,
|
||||
void **priv_data
|
||||
)
|
||||
{
|
||||
return (void *)(NvUPtr)start;
|
||||
}
|
||||
|
||||
void NV_API_CALL os_unmap_user_space(
|
||||
void *address,
|
||||
NvU64 size,
|
||||
void *priv_data
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
NV_STATUS NV_API_CALL os_match_mmap_offset(
|
||||
void *pAllocPrivate,
|
||||
NvU64 offset,
|
||||
NvU64 *pPageIndex
|
||||
)
|
||||
{
|
||||
nv_alloc_t *at = pAllocPrivate;
|
||||
NvU64 i;
|
||||
|
||||
for (i = 0; i < at->num_pages; i++)
|
||||
{
|
||||
if (at->flags.contig)
|
||||
{
|
||||
if (offset == (at->page_table[0]->phys_addr + (i * PAGE_SIZE)))
|
||||
{
|
||||
*pPageIndex = i;
|
||||
return NV_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset == at->page_table[i]->phys_addr)
|
||||
{
|
||||
*pPageIndex = i;
|
||||
return NV_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NV_ERR_OBJECT_NOT_FOUND;
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2016-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "linux_nvswitch.h"
|
||||
#include "nv-procfs.h"
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
||||
#if defined(CONFIG_PROC_FS)
|
||||
|
||||
#define NV_DEFINE_SINGLE_NVSWITCH_PROCFS_FILE(name) \
|
||||
NV_DEFINE_SINGLE_PROCFS_FILE_READ_ONLY(name, nv_system_pm_lock)
|
||||
|
||||
#define NVSWITCH_PROCFS_DIR "driver/nvidia-nvswitch"
|
||||
|
||||
static struct proc_dir_entry *nvswitch_procfs_dir;
|
||||
static struct proc_dir_entry *nvswitch_permissions;
|
||||
static struct proc_dir_entry *nvswitch_procfs_devices;
|
||||
|
||||
static int
|
||||
nv_procfs_read_permissions
|
||||
(
|
||||
struct seq_file *s,
|
||||
void *v
|
||||
)
|
||||
{
|
||||
// Restrict device node permissions - 0666. Used by nvidia-modprobe.
|
||||
seq_printf(s, "%s: %u\n", "DeviceFileMode", 438);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NV_DEFINE_SINGLE_NVSWITCH_PROCFS_FILE(permissions);
|
||||
|
||||
static int
|
||||
nv_procfs_read_device_info
|
||||
(
|
||||
struct seq_file *s,
|
||||
void *v
|
||||
)
|
||||
{
|
||||
NVSWITCH_DEV *nvswitch_dev = s->private;
|
||||
|
||||
if (!nvswitch_dev)
|
||||
{
|
||||
NVSWITCH_OS_ASSERT(0);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
seq_printf(s, "BIOS Version: ");
|
||||
|
||||
if (nvswitch_dev->bios_ver)
|
||||
{
|
||||
seq_printf(s, "%02llx.%02llx.%02llx.%02llx.%02llx\n",
|
||||
nvswitch_dev->bios_ver >> 32,
|
||||
(nvswitch_dev->bios_ver >> 24) & 0xFF,
|
||||
(nvswitch_dev->bios_ver >> 16) & 0xFF,
|
||||
(nvswitch_dev->bios_ver >> 8) & 0xFF,
|
||||
nvswitch_dev->bios_ver & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
seq_printf(s, "N/A\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NV_DEFINE_SINGLE_NVSWITCH_PROCFS_FILE(device_info);
|
||||
|
||||
void
|
||||
nvswitch_procfs_device_remove
|
||||
(
|
||||
NVSWITCH_DEV *nvswitch_dev
|
||||
)
|
||||
{
|
||||
if (!nvswitch_dev || !nvswitch_dev->procfs_dir)
|
||||
{
|
||||
NVSWITCH_OS_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
proc_remove(nvswitch_dev->procfs_dir);
|
||||
nvswitch_dev->procfs_dir = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
nvswitch_procfs_device_add
|
||||
(
|
||||
NVSWITCH_DEV *nvswitch_dev
|
||||
)
|
||||
{
|
||||
struct pci_dev *pci_dev;
|
||||
struct proc_dir_entry *device_dir, *entry;
|
||||
char name[32];
|
||||
|
||||
if (!nvswitch_dev || !nvswitch_dev->pci_dev)
|
||||
{
|
||||
NVSWITCH_OS_ASSERT(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pci_dev = nvswitch_dev->pci_dev;
|
||||
|
||||
snprintf(name, sizeof(name), "%04x:%02x:%02x.%1x",
|
||||
NV_PCI_DOMAIN_NUMBER(pci_dev), NV_PCI_BUS_NUMBER(pci_dev),
|
||||
NV_PCI_SLOT_NUMBER(pci_dev), PCI_FUNC(pci_dev->devfn));
|
||||
|
||||
device_dir = NV_CREATE_PROC_DIR(name, nvswitch_procfs_devices);
|
||||
if (!device_dir)
|
||||
return -1;
|
||||
|
||||
nvswitch_dev->procfs_dir = device_dir;
|
||||
|
||||
entry = NV_CREATE_PROC_FILE("information", device_dir, device_info,
|
||||
nvswitch_dev);
|
||||
if (!entry)
|
||||
goto failed;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
nvswitch_procfs_device_remove(nvswitch_dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
nvswitch_procfs_exit
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
if (!nvswitch_procfs_dir)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
proc_remove(nvswitch_procfs_dir);
|
||||
nvswitch_procfs_dir = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
nvswitch_procfs_init
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
nvswitch_procfs_dir = NV_CREATE_PROC_DIR(NVSWITCH_PROCFS_DIR, NULL);
|
||||
if (!nvswitch_procfs_dir)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
nvswitch_permissions = NV_CREATE_PROC_FILE("permissions",
|
||||
nvswitch_procfs_dir,
|
||||
permissions,
|
||||
NULL);
|
||||
if (!nvswitch_permissions)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
nvswitch_procfs_devices = NV_CREATE_PROC_DIR("devices", nvswitch_procfs_dir);
|
||||
if (!nvswitch_procfs_devices)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
|
||||
nvswitch_procfs_exit();
|
||||
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
#else // !CONFIG_PROC_FS
|
||||
|
||||
int nvswitch_procfs_init(void) { return 0; }
|
||||
void nvswitch_procfs_exit(void) { }
|
||||
int nvswitch_procfs_device_add(NVSWITCH_DEV *nvswitch_dev) { return 0; }
|
||||
void nvswitch_procfs_device_remove(NVSWITCH_DEV *nvswitch_dev) { }
|
||||
|
||||
#endif // CONFIG_PROC_FS
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2015 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _RMP2PDEFINES_H_
|
||||
#define _RMP2PDEFINES_H_
|
||||
|
||||
#define NVRM_P2P_PAGESIZE_SMALL_4K (4 << 10)
|
||||
#define NVRM_P2P_PAGESIZE_BIG_64K (64 << 10)
|
||||
#define NVRM_P2P_PAGESIZE_BIG_128K (128 << 10)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user