|  | /* Copyright (c) 2015 Google Inc | 
|  | * Davide Libenzi <dlibenzi@google.com> | 
|  | * See LICENSE for details. | 
|  | */ | 
|  |  | 
|  | #include <ros/common.h> | 
|  | #include <compiler.h> | 
|  | #include <kmalloc.h> | 
|  | #include <kthread.h> | 
|  | #include <string.h> | 
|  | #include <stdio.h> | 
|  | #include <assert.h> | 
|  | #include <error.h> | 
|  | #include <pmap.h> | 
|  | #include <umem.h> | 
|  | #include <smp.h> | 
|  | #include <core_set.h> | 
|  | #include <completion.h> | 
|  | #include <arch/uaccess.h> | 
|  | #include <arch/msr.h> | 
|  |  | 
|  | struct smp_read_values { | 
|  | const struct msr_address *msra; | 
|  | struct msr_value *msrv; | 
|  | int err; | 
|  | }; | 
|  |  | 
|  | struct smp_write_values { | 
|  | const struct msr_address *msra; | 
|  | const struct msr_value *msrv; | 
|  | int err; | 
|  | }; | 
|  |  | 
|  | static void msr_smp_read(void *opaque) | 
|  | { | 
|  | struct smp_read_values *srv = (struct smp_read_values *) opaque; | 
|  | int err, coreno = core_id(); | 
|  | uint32_t addr; | 
|  | uint64_t value; | 
|  |  | 
|  | err = msr_get_core_address(coreno, srv->msra, &addr); | 
|  | if (err) | 
|  | goto errout; | 
|  | err = read_msr_safe(addr, &value); | 
|  | if (err) | 
|  | goto errout; | 
|  | err = msr_set_core_value(coreno, value, srv->msrv); | 
|  | if (err) | 
|  | goto errout; | 
|  |  | 
|  | return; | 
|  |  | 
|  | errout: | 
|  | srv->err = err; | 
|  | } | 
|  |  | 
|  | int msr_cores_read(const struct core_set *cset, const struct msr_address *msra, | 
|  | struct msr_value *msrv) | 
|  | { | 
|  | int err; | 
|  | struct smp_read_values srv; | 
|  |  | 
|  | ZERO_DATA(srv); | 
|  | srv.msra = msra; | 
|  | srv.msrv = msrv; | 
|  | srv.err = 0; | 
|  | smp_do_in_cores(cset, msr_smp_read, &srv); | 
|  |  | 
|  | return srv.err; | 
|  | } | 
|  |  | 
|  | int msr_core_read(unsigned int coreno, uint32_t addr, uint64_t *value) | 
|  | { | 
|  | int err; | 
|  | struct core_set cset; | 
|  | struct msr_address msra; | 
|  | struct msr_value msrv; | 
|  |  | 
|  | core_set_init(&cset); | 
|  | core_set_setcpu(&cset, coreno); | 
|  | msr_set_address(&msra, addr); | 
|  | msr_set_values(&msrv, NULL, 0); | 
|  | err = msr_cores_read(&cset, &msra, &msrv); | 
|  | *value = msrv.value; | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  | static void msr_smp_write(void *opaque) | 
|  | { | 
|  | struct smp_write_values *swv = (struct smp_write_values *) opaque; | 
|  | int err, coreno = core_id(); | 
|  | uint32_t addr; | 
|  | uint64_t value; | 
|  |  | 
|  | err = msr_get_core_address(coreno, swv->msra, &addr); | 
|  | if (err) | 
|  | goto errout; | 
|  | err = msr_get_core_value(coreno, swv->msrv, &value); | 
|  | if (err) | 
|  | goto errout; | 
|  | err = write_msr_safe(addr, value); | 
|  | if (err) | 
|  | goto errout; | 
|  |  | 
|  | return; | 
|  |  | 
|  | errout: | 
|  | swv->err = err; | 
|  | } | 
|  |  | 
|  | int msr_cores_write(const struct core_set *cset, const struct msr_address *msra, | 
|  | const struct msr_value *msrv) | 
|  | { | 
|  | struct smp_write_values swv; | 
|  |  | 
|  | ZERO_DATA(swv); | 
|  | swv.msra = msra; | 
|  | swv.msrv = msrv; | 
|  | swv.err = 0; | 
|  | smp_do_in_cores(cset, msr_smp_write, &swv); | 
|  |  | 
|  | return swv.err; | 
|  | } | 
|  |  | 
|  | int msr_core_write(unsigned int coreno, uint32_t addr, uint64_t value) | 
|  | { | 
|  | struct core_set cset; | 
|  | struct msr_address msra; | 
|  | struct msr_value msrv; | 
|  |  | 
|  | core_set_init(&cset); | 
|  | core_set_setcpu(&cset, coreno); | 
|  | msr_set_address(&msra, addr); | 
|  | msr_set_value(&msrv, value); | 
|  |  | 
|  | return msr_cores_write(&cset, &msra, &msrv); | 
|  | } |