| /* Copyright (c) 2015 Google Inc |
| * Davide Libenzi <dlibenzi@google.com> |
| * See LICENSE for details. |
| */ |
| |
| #pragma once |
| |
| #include <sys/types.h> |
| #include <ros/errno.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <core_set.h> |
| |
| /* The msr_address and msr_value structures allow to specify either a single |
| * address/value for all cores, or dedicated ones for every core. |
| * This allow a single logical call to msr_cores_read()/msr_cores_write() APIs, |
| * to read/write MSRs at different addresses and using different values. |
| */ |
| struct msr_address { |
| uint32_t addr; |
| const uint32_t *addresses; |
| size_t num_addresses; |
| }; |
| |
| struct msr_value { |
| uint64_t value; |
| uint64_t *values; |
| size_t num_values; |
| }; |
| |
| int msr_cores_read(const struct core_set *cset, const struct msr_address *msra, |
| struct msr_value *msrv); |
| int msr_core_read(unsigned int core, uint32_t addr, uint64_t *value); |
| int msr_cores_write(const struct core_set *cset, const struct msr_address *msra, |
| const struct msr_value *msrv); |
| int msr_core_write(unsigned int core, uint32_t addr, uint64_t value); |
| |
| static inline void msr_set_address(struct msr_address *msra, uint32_t addr) |
| { |
| ZERO_DATA(*msra); |
| msra->addr = addr; |
| } |
| |
| static inline void msr_set_addresses(struct msr_address *msra, |
| const uint32_t *addresses, |
| size_t num_addresses) |
| { |
| ZERO_DATA(*msra); |
| msra->addresses = addresses; |
| msra->num_addresses = num_addresses; |
| } |
| |
| static inline int msr_get_core_address(unsigned int coreno, |
| const struct msr_address *msra, |
| uint32_t *paddr) |
| { |
| if (msra->addresses != NULL) { |
| if (coreno >= (unsigned int) msra->num_addresses) |
| return -ERANGE; |
| |
| *paddr = msra->addresses[coreno]; |
| } else { |
| *paddr = msra->addr; |
| } |
| |
| return 0; |
| } |
| |
| static inline void msr_set_value(struct msr_value *msrv, uint64_t value) |
| { |
| ZERO_DATA(*msrv); |
| msrv->value = value; |
| } |
| |
| static inline void msr_set_values(struct msr_value *msrv, |
| const uint64_t *values, size_t num_values) |
| { |
| ZERO_DATA(*msrv); |
| |
| /* Avoid supporting two APIs, one for setting const values, and one for |
| * setting the non const ones. |
| */ |
| msrv->values = (uint64_t *) values; |
| msrv->num_values = num_values; |
| } |
| |
| static inline int msr_set_core_value(unsigned int coreno, uint64_t value, |
| struct msr_value *msrv) |
| { |
| if (msrv->values != NULL) { |
| if (coreno >= (unsigned int) msrv->num_values) |
| return -ERANGE; |
| |
| msrv->values[coreno] = value; |
| } else { |
| msrv->value = value; |
| } |
| |
| return 0; |
| } |
| |
| static inline int msr_get_core_value(unsigned int coreno, |
| const struct msr_value *msrv, |
| uint64_t *pvalue) |
| { |
| if (msrv->values != NULL) { |
| if (coreno >= (unsigned int) msrv->num_values) |
| return -ERANGE; |
| |
| *pvalue = msrv->values[coreno]; |
| } else { |
| *pvalue = msrv->value; |
| } |
| |
| return 0; |
| } |