Beispiel #1
0
int get_dram_rapl_limit(const unsigned socket, struct rapl_limit *limit)
{
    static uint64_t *rapl_flags = NULL;
    sockets_assert(&socket, __LINE__, __FILE__);

    if (rapl_flags == NULL)
    {
        if (rapl_storage(NULL, &rapl_flags))
        {
            return -1;
        }
    }

    /* Make sure the dram power limit register exists. */
    if ((limit != NULL) && (*rapl_flags & DRAM_POWER_LIMIT))
    {
        read_msr_by_coord(socket, 0, 0, MSR_DRAM_POWER_LIMIT, &(limit->bits));
        calc_std_rapl_limit(socket, limit);
    }
    else if (limit != NULL)
    {
        libmsr_error_handler("get_dram_rapl_limit(): DRAM domain RAPL power limit not supported on this architecture", LIBMSR_ERROR_PLATFORM_NOT_SUPPORTED, getenv("HOSTNAME"), __FILE__, __LINE__);
        return -1;
    }
    return 0;
}
Beispiel #2
0
/// @brief Create the human-readable power settings if the user-supplied bits.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] limit Data for desired power limit.
///
/// @param [in] offset Power limit 1 (lower) or power limit 2 (upper)
///        identifier. Power limit 2 only applies to package domain.
///
/// @return 0 if successful, else -1 if translate() failed.
static int calc_rapl_from_bits(const unsigned socket, struct rapl_limit *limit, const unsigned offset)
{
    uint64_t watts_bits = 0;
    uint64_t seconds_bits = 0;
    int ret = 0;

    sockets_assert(&socket, __LINE__, __FILE__);

#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (calc_rapl_from_bits)\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif
    watts_bits = MASK_VAL(limit->bits, 14+offset, 0+offset);
    seconds_bits = MASK_VAL(limit->bits, 23+offset, 17+offset);

    // We have been given the bits to be written to the msr.
    // For sake of completeness, translate these into watts and seconds.
    ret = translate(socket, &watts_bits, &limit->watts, BITS_TO_WATTS);
    // If the offset is > 31 (we are writing the upper PKG limit), then no
    // translation needed
    if (offset < 32)
    {
        ret += translate(socket, &seconds_bits, &limit->seconds, BITS_TO_SECONDS_STD);
    }
    else
    {
        limit->seconds = seconds_bits;
    }
    if (ret < 0)
    {
        libmsr_error_handler("calc_rapl_from_bits(): Translation from bits to values failed", LIBMSR_ERROR_RAPL_INIT, getenv("HOSTNAME"), __FILE__, __LINE__);
        return ret;
    }
    return 0;
}
Beispiel #3
0
/// @brief Translates human-readable power settings into raw 64-bit format.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] limit Data for desired power limit.
///
/// @param [in] offset Power limit 1 (lower) or power limit 2 (upper)
///        identifier. Power limit 2 only applies to package domain.
///
/// @return 0 if successful, else -1 if rapl_storage() fails or if the Watts
/// value or seconds value overflow the bit field.
static int calc_rapl_bits(const unsigned socket, struct rapl_limit *limit, const unsigned offset)
{
    uint64_t watts_bits = 0;
    uint64_t seconds_bits = 0;
    sockets_assert(&socket, __LINE__, __FILE__);

    watts_bits = MASK_VAL(limit->bits, 14+offset, 0+offset);
    seconds_bits = MASK_VAL(limit->bits, 23+offset, 17+offset);

#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (calc_rapl_bits)\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif
    /*
     * We have been given watts and seconds and need to translate these into
     * bit values.
     * If offset is >= 32 (we are setting the 2nd pkg limit), we don't need time
     * conversion.
     */
    if (offset >= 32)
    {
        seconds_bits = (uint64_t)limit->seconds; // unit is milliseconds
        //translate(socket, &seconds_bits, &limit->seconds, SECONDS_TO_BITS_STD);
    }
    else
    {
        translate(socket, &seconds_bits, &limit->seconds, SECONDS_TO_BITS_STD);
    }
    /* There is only 1 translation for watts (so far). */
    translate(socket, &watts_bits, &limit->watts, WATTS_TO_BITS);
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "Converted %lf watts into %lx bits.\n", limit->watts, watts_bits);
    fprintf(stderr, "Converted %lf seconds into %lx bits.\n", limit->seconds, seconds_bits);
#endif
    /* Check to make sure the watts value does not overflow the bit field. */
    if (watts_bits & 0xFFFFFFFFFFFF8000)
    {
        libmsr_error_handler("calc_rapl_bits(): Translation from bits to values failed", LIBMSR_ERROR_INVAL, getenv("HOSTNAME"), __FILE__, __LINE__);
        return -1;
    }
    watts_bits <<= 0 + offset;
    /* Check to make sure the seconds value does not overflow the bit field. */
    if (seconds_bits & 0xFFFFFFFFFFFFFF80)
    {
        libmsr_error_handler("calc_rapl_bits(): Seconds value is too large", LIBMSR_ERROR_INVAL, getenv("HOSTNAME"), __FILE__, __LINE__);
        return -1;
    }
    seconds_bits <<= 17 + offset;
    limit->bits |= watts_bits;
    limit->bits |= seconds_bits;
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "calculated rapl bits\n");
#endif
    return 0;
}
Beispiel #4
0
int get_rapl_power_info(const unsigned socket, struct rapl_power_info *info)
{
    uint64_t val = 0;
    static uint64_t *rapl_flags = NULL;

    sockets_assert(&socket, __LINE__, __FILE__);

    if (rapl_flags == NULL)
    {
        if (rapl_storage(NULL, &rapl_flags))
        {
            libmsr_error_handler("get_rapl_power_info(): Cannot load rapl_flags", LIBMSR_ERROR_RAPL_INIT, getenv("HOSTNAME"), __FILE__, __LINE__);
            return -1;
        }
    }
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (get_rapl_power_info)\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif
    if (*rapl_flags & PKG_POWER_INFO)
    {
        read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_INFO, &(info->msr_pkg_power_info));
        val = MASK_VAL(info->msr_pkg_power_info, 54, 48);
        translate(socket, &val, &(info->pkg_max_window), BITS_TO_SECONDS_STD);

        val = MASK_VAL(info->msr_pkg_power_info, 46, 32);
        translate(socket, &val, &(info->pkg_max_power), BITS_TO_WATTS);

        val = MASK_VAL(info->msr_pkg_power_info, 30, 16);
        translate(socket, &val, &(info->pkg_min_power), BITS_TO_WATTS);

        val = MASK_VAL(info->msr_pkg_power_info, 14, 0);
        translate(socket, &val, &(info->pkg_therm_power), BITS_TO_WATTS);
    }
    if (*rapl_flags & DRAM_POWER_INFO)
    {
        read_msr_by_coord(socket, 0, 0, MSR_DRAM_POWER_INFO, &(info->msr_dram_power_info));

        val = MASK_VAL(info->msr_dram_power_info, 54, 48);
        translate(socket, &val, &(info->dram_max_window), BITS_TO_SECONDS_STD);

        val = MASK_VAL(info->msr_dram_power_info, 46, 32);
        translate(socket, &val, &(info->dram_max_power), BITS_TO_WATTS);

        val = MASK_VAL(info->msr_dram_power_info, 30, 16);
        translate(socket, &val, &(info->dram_min_power), BITS_TO_WATTS);

        val = MASK_VAL(info->msr_dram_power_info, 14, 0);
        translate(socket, &val, &(info->dram_therm_power), BITS_TO_WATTS);
    }
    return 0;
}
Beispiel #5
0
/// @brief Determine how the user setup the package domain RAPL power limits
/// and setup other limit accordingly.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] limit1 Data for desired power limit 1 (lower).
///
/// @param [out] limit2 Data for desired power limit 2 (upper).
///
/// @return 0 if successful, else -1 if calc_rapl_bits() or
/// calc_rapl_from_bits() fails.
static int calc_pkg_rapl_limit(const unsigned socket, struct rapl_limit *limit1, struct rapl_limit *limit2)
{
    sockets_assert(&socket, __LINE__, __FILE__);
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (calc_pkg_rapl_limit)\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif

    /* If we have been given a lower rapl limit. */
    if (limit1 != NULL)
    {
        if (limit1->bits)
        {
            if (calc_rapl_from_bits(socket, limit1, 0))
            {
                return -1;
            }
        }
        else
        {
            if (calc_rapl_bits(socket, limit1, 0))
            {
                return -1;
            }
        }
    }
    /* If we have been given an upper rapl limit. */
    if (limit2 != NULL)
    {
        if (limit2->bits)
        {
            if (calc_rapl_from_bits(socket, limit2, 32))
            {
                return -1;
            }
        }
        else
        {
            if (calc_rapl_bits(socket, limit2, 32))
            {
                return -1;
            }
        }
    }
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "pkg calculated\n");
#endif
    return 0;
}
Beispiel #6
0
int write_msr_by_coord(unsigned socket, unsigned core, unsigned thread, off_t msr, uint64_t val)
{
    static uint64_t coresPerSocket = 0;
    static uint64_t threadsPerCore = 0;

    sockets_assert(&socket, __LINE__, __FILE__);
    cores_assert(&core, __LINE__, __FILE__);
    threads_assert(&thread, __LINE__, __FILE__);
    if (coresPerSocket == 0 || threadsPerCore == 0)
    {
        core_config(&coresPerSocket, &threadsPerCore, NULL, NULL);
    }
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s %s::%d (write_msr_by_coord) socket=%d core=%d thread=%d msr=%lu (0x%lx) val=%lu\n", getenv("HOSTNAME"), LIBMSR_DEBUG_TAG, __FILE__, __LINE__, socket, core, thread, msr, msr, val);
    return write_msr_by_idx_and_verify(devidx(socket, core, thread), msr, val);
#endif
    return write_msr_by_idx(devidx(socket, core, thread), msr, val);
}
Beispiel #7
0
int read_msr_by_coord_batch(unsigned socket, unsigned core, unsigned thread, off_t msr, uint64_t **val, int batchnum)
{
    static uint64_t coresPerSocket = 0;
    static uint64_t threadsPerCore = 0;

#ifdef BATCH_DEBUG
    fprintf(stderr, "%s %s %s::%d (read_msr_by_coord_batch) socket=%d core=%d thread=%d msr=%lu (0x%lx)\n", getenv("HOSTNAME"), LIBMSR_DEBUG_TAG, __FILE__, __LINE__, socket, core, thread, msr, msr);
#endif
    sockets_assert(&socket, __LINE__, __FILE__);
    cores_assert(&core, __LINE__, __FILE__);
    threads_assert(&thread, __LINE__, __FILE__);
    if (coresPerSocket == 0 || threadsPerCore == 0)
    {
        core_config(&coresPerSocket, &threadsPerCore, NULL, NULL);
    }
#ifdef BATCH_DEBUG
    fprintf(stderr, "DEBUG: passed operation on msr 0x%lx (socket %u, core %u, thread %u) to BATCH OPS with destination %p\n", msr, socket, core, thread, val);
#endif
    create_batch_op(msr, devidx(socket, core, thread), val, batchnum);
    return 0;
}
Beispiel #8
0
int read_msr_by_coord(unsigned socket, unsigned core, unsigned thread, off_t msr, uint64_t *val)
{
    static uint64_t coresPerSocket = 0;
    static uint64_t threadsPerCore = 0;

#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s %s::%d (read_msr_by_coord) socket=%d core=%d thread=%d msr=%lu (0x%lx)\n", getenv("HOSTNAME"), LIBMSR_DEBUG_TAG, __FILE__, __LINE__, socket, core, thread, msr, msr);
#endif
    sockets_assert(&socket, __LINE__, __FILE__);
    cores_assert(&core, __LINE__, __FILE__);
    threads_assert(&thread, __LINE__, __FILE__);
    if (val == NULL)
    {
        libmsr_error_handler("read_msr_by_coord(): Received NULL pointer", LIBMSR_ERROR_MSR_READ, getenv("HOSTNAME"), __FILE__, __LINE__);
    }
    if (coresPerSocket == 0 || threadsPerCore == 0)
    {
        core_config(&coresPerSocket, &threadsPerCore, NULL, NULL);
    }
    return read_msr_by_idx(devidx(socket, core, thread), msr, val);
}
Beispiel #9
0
/// @brief Determine how the user setup non-package RAPL power limits and setup
/// the data for the other limit accordingly.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] limit Data for desired power limit.
///
/// @return 0 if successful, else -1 if calc_rapl_from_bits() or
/// calc_rapl_bits() fails.
static int calc_std_rapl_limit(const unsigned socket, struct rapl_limit *limit)
{
    sockets_assert(&socket, __LINE__, __FILE__);
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (calc_std_rapl_limit)\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif

    if (limit->bits)
    {
        if (calc_rapl_from_bits(socket, limit, 0))
        {
            return -1;
        }
    }
    else
    {
        if (calc_rapl_bits(socket, limit, 0))
        {
            return -1;
        }
    }
    return 0;
}
Beispiel #10
0
int set_dram_rapl_limit(const unsigned socket, struct rapl_limit *limit)
{
    uint64_t dram_limit = 0;
    static uint64_t *rapl_flags = NULL;

    sockets_assert(&socket, __LINE__, __FILE__);
    if (rapl_flags == NULL)
    {
        if (rapl_storage(NULL, &rapl_flags))
        {
            return -1;
        }
    }
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (set_dram_rapl_limit)\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif
    /* Make sure the dram power limit register exists. */
    if (*rapl_flags & DRAM_POWER_LIMIT)
    {
        if (limit != NULL)
        {
            if (calc_std_rapl_limit(socket, limit))
            {
                return -1;
            }
            dram_limit |= limit->bits | (1LL << 15);
            write_msr_by_coord(socket, 0, 0, MSR_DRAM_POWER_LIMIT, dram_limit);
        }
    }
    else
    {
        libmsr_error_handler("set_dram_rapl_limit(): DRAM domain RAPL limit not supported on this architecture", LIBMSR_ERROR_PLATFORM_NOT_SUPPORTED, getenv("HOSTNAME"), __FILE__, __LINE__);
        return -1;
    }
    return 0;
}
Beispiel #11
0
int set_pkg_rapl_limit(const unsigned socket, struct rapl_limit *limit1, struct rapl_limit *limit2)
{
    uint64_t pkg_limit = 0;
    static uint64_t *rapl_flags = NULL;
    uint64_t currentval = 0;
    int ret = 0;
    sockets_assert(&socket, __LINE__, __FILE__);

    if (rapl_flags == NULL)
    {
        if (rapl_storage(NULL, &rapl_flags))
        {
            return -1;
        }
    }
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "%s %s::%d DEBUG: (set_pkg_rapl_limit) flags are at %p\n", getenv("HOSTNAME"), __FILE__, __LINE__, rapl_flags);
#endif

    /* Make sure the pkg power limit register exists. */
    if (*rapl_flags & PKG_POWER_LIMIT)
    {
        /* If there is only one limit, grab the other existing one. */
        if (limit1 == NULL)
        {
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: only one rapl limit, retrieving any existing power limits\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif
            ret = read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, &currentval);
            /* We want to keep the lower limit so mask off all other bits. */
            pkg_limit |= currentval & 0x00000000FFFFFFFF;
        }
        else if (limit2 == NULL)
        {
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: only one rapl limit, retrieving any existing power limits\n", getenv("HOSTNAME"), __FILE__, __LINE__);
#endif
            ret = read_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, &currentval);
            /* We want to keep the upper limit so mask off all other bits. */
            pkg_limit |= currentval & 0xFFFFFFFF00000000;
        }
        if (calc_pkg_rapl_limit(socket, limit1, limit2))
        {
            return -1;
        }
        /* Enable the rapl limit (15 && 47) and turn on clamping (16 && 48). */
        if (limit1 != NULL)
        {
            pkg_limit |= limit1->bits | (1LL << 15) | (1LL << 16);
        }
        if (limit2 != NULL)
        {
            pkg_limit |= limit2->bits | (1LL << 47) | (1LL << 48);
        }
        if (limit1 != NULL || limit2 != NULL)
        {
            ret += write_msr_by_coord(socket, 0, 0, MSR_PKG_POWER_LIMIT, pkg_limit);
        }
    }
    else
    {
        libmsr_error_handler("set_pkg_rapl_limit(): PKG domain RAPL limit not supported on this architecture", LIBMSR_ERROR_PLATFORM_NOT_SUPPORTED, getenv("HOSTNAME"), __FILE__, __LINE__);
        return -1;
    }
#ifdef LIBMSR_DEBUG
    fprintf(stderr, "pkg set\n");
#endif
    return ret;
}
Beispiel #12
0
/// @brief Translate any user-desired values to the format expected in the MSRs
/// and vice versa.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] bits Raw bit field value.
///
/// @param [out] units Human-readable value.
///
/// @param [in] type libmsr_unit_conversions_e unit conversion identifier.
///
/// @return 0 upon function completion or upon converting bits to Joules for
/// DRAM RAPL power domain for 0x3F (Haswell) platform.
static int translate(const unsigned socket, uint64_t *bits, double *units, int type)
{
    static int init = 0;
    double logremainder = 0.0;
    static uint64_t sockets = 0;
    static uint64_t model = 0;
    static struct rapl_units *ru = NULL;
    uint64_t timeval_z = 0;
    uint64_t timeval_y = 0;

#ifdef LIBMSR_DEBUG
    fprintf(stderr, "DEBUG: (translate) bits are at %p\n", bits);
#endif
    if (sockets == 0)
    {
        sockets = num_sockets();
    }
    if (model == 0)
    {
        cpuid_get_model(&model);
    }
    sockets_assert(&socket, __LINE__, __FILE__);

    if (!init)
    {
        init = 1;
        ru = (struct rapl_units *) libmsr_calloc(sockets, sizeof(struct rapl_units));
        get_rapl_power_unit(ru);
    }
    switch(type)
    {
        case BITS_TO_WATTS:
            *units = (double)(*bits) * ru[socket].watts;
            break;
        case BITS_TO_JOULES_DRAM:
            if (model == 0x3F || model == 0x4F || model == 0x55)
            {
                *units = (double)(*bits) / STD_ENERGY_UNIT;
#ifdef LIBMSR_DEBUG
                fprintf(stderr, "DEBUG: (translate_dram) %f is %f joules\n", (double)*bits, *units);
#endif
                return 0;
            }
            /* No break statement, if not Haswell do standard stuff. */
        case BITS_TO_JOULES:
            *units = (double)(*bits) / ru[socket].joules;
            break;
        case WATTS_TO_BITS:
            *bits  = (uint64_t)((*units) / ru[socket].watts);
            break;
        case JOULES_TO_BITS:
            /// @todo Currently unused, but if it ever is used, we need a fix for Haswell.
            *bits  = (uint64_t)((*units) * ru[socket].joules);
            break;
        case BITS_TO_SECONDS_STD:
            timeval_y = *bits & 0x1F;
            timeval_z = (*bits & 0x60) >> 5;
            /* Dividing by time unit because it's stored as (1/(2^TU))^-1. */
            *units = ((1 + 0.25 * timeval_z) * pow(2.0,(double)timeval_y)) / ru[socket].seconds;
            // Temporary fix for haswell
            //    if (model == 0x3F)
            //    {
            //        *units = *units * 2.5 + 15.0;
            //    }
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: timeval_z is %lx, timeval_y is %lx, units is %lf, bits is %lx\n", getenv("HOSTNAME"), __FILE__, __LINE__, timeval_z, timeval_y, *units, *bits);
#endif
            break;
        case SECONDS_TO_BITS_STD:
            // Temporary fix for haswell
            //    if (model == 0x3F)
            //    {
            //        *units = *units / 2.5 - 15;
            //    }
            /* Store the whole number part of the log2. */
            timeval_y = (uint64_t)log2(*units * ru[socket].seconds);
            /* Store the mantissa of the log2. */
            logremainder = (double)log2(*units * ru[socket].seconds) - (double)timeval_y;
            timeval_z = 0;
            /* Based on the mantissa, choose the appropriate multiplier. */
            if (logremainder > 0.15 && logremainder <= 0.45)
            {
                timeval_z = 1;
            }
            else if (logremainder > 0.45 && logremainder <= 0.7)
            {
                timeval_z = 2;
            }
            else if (logremainder > 0.7)
            {
                timeval_z = 3;
            }
            /* Store the bits in the Intel specified format. */
            *bits = (uint64_t)(timeval_y | (timeval_z << 5));
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: timeval_z is %lx, timeval_y is %lx, units is %lf, bits is %lx, remainder is %lf\n", getenv("HOSTNAME"), __FILE__, __LINE__, timeval_z, timeval_y, *units, *bits, logremainder);
#endif
            break;
        default:
            fprintf(stderr, "%s:%d  Unknown value %d.  This is bad.\n", __FILE__, __LINE__, type);
            *bits = -1;
            *units= -1.0;
            break;
    }
    return 0;
}