| /* 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); |
| } |