vm exit handler for xsetbv
[akaros.git] / kern / arch / x86 / msr.c
1 /* Copyright (c) 2015 Google Inc
2  * Davide Libenzi <dlibenzi@google.com>
3  * See LICENSE for details.
4  */
5
6 #include <ros/common.h>
7 #include <compiler.h>
8 #include <kmalloc.h>
9 #include <kthread.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <assert.h>
13 #include <error.h>
14 #include <pmap.h>
15 #include <umem.h>
16 #include <smp.h>
17 #include <atomic.h>
18 #include <core_set.h>
19 #include <completion.h>
20 #include <arch/uaccess.h>
21 #include <arch/msr.h>
22
23 struct smp_read_values {
24         const struct msr_address *msra;
25         struct msr_value *msrv;
26         atomic_t err;
27 };
28
29 struct smp_write_values {
30         const struct msr_address *msra;
31         const struct msr_value *msrv;
32         atomic_t err;
33 };
34
35 static void msr_smp_read(void *opaque)
36 {
37         struct smp_read_values *srv = (struct smp_read_values *) opaque;
38         int err, coreno = core_id();
39         uint32_t addr;
40         uint64_t value;
41
42         err = msr_get_core_address(coreno, srv->msra, &addr);
43         if (likely(!err)) {
44                 err = safe_read_msr(addr, &value);
45                 if (likely(!err))
46                         err = msr_set_core_value(coreno, value, srv->msrv);
47         }
48         if (unlikely(err))
49                 atomic_cas(&srv->err, 0, err);
50 }
51
52 int msr_cores_read(const struct core_set *cset, const struct msr_address *msra,
53                                    struct msr_value *msrv)
54 {
55         int err;
56         struct smp_read_values srv;
57
58         ZERO_DATA(srv);
59         srv.msra = msra;
60         srv.msrv = msrv;
61         atomic_init(&srv.err, 0);
62         smp_do_in_cores(cset, msr_smp_read, &srv);
63
64         return (int) atomic_read(&srv.err);
65 }
66
67 int msr_core_read(unsigned int coreno, uint32_t addr, uint64_t *value)
68 {
69         int err;
70         struct core_set cset;
71         struct msr_address msra;
72         struct msr_value msrv;
73
74         core_set_init(&cset);
75         core_set_setcpu(&cset, coreno);
76         msr_set_address(&msra, addr);
77         msr_set_values(&msrv, NULL, 0);
78         err = msr_cores_read(&cset, &msra, &msrv);
79         *value = msrv.value;
80
81         return err;
82 }
83
84 static void msr_smp_write(void *opaque)
85 {
86         struct smp_write_values *swv = (struct smp_write_values *) opaque;
87         int err, coreno = core_id();
88         uint32_t addr;
89         uint64_t value;
90
91         err = msr_get_core_address(coreno, swv->msra, &addr);
92         if (likely(!err)) {
93                 err = msr_get_core_value(coreno, swv->msrv, &value);
94                 if (likely(!err))
95                         err = safe_write_msr(addr, value);
96         }
97         if (unlikely(err))
98                 atomic_cas(&swv->err, 0, err);
99 }
100
101 int msr_cores_write(const struct core_set *cset, const struct msr_address *msra,
102                                         const struct msr_value *msrv)
103 {
104         struct smp_write_values swv;
105
106         ZERO_DATA(swv);
107         swv.msra = msra;
108         swv.msrv = msrv;
109         atomic_init(&swv.err, 0);
110         smp_do_in_cores(cset, msr_smp_write, &swv);
111
112         return (int) atomic_read(&swv.err);
113 }
114
115 int msr_core_write(unsigned int coreno, uint32_t addr, uint64_t value)
116 {
117         struct core_set cset;
118         struct msr_address msra;
119         struct msr_value msrv;
120
121         core_set_init(&cset);
122         core_set_setcpu(&cset, coreno);
123         msr_set_address(&msra, addr);
124         msr_set_value(&msrv, value);
125
126         return msr_cores_write(&cset, &msra, &msrv);
127 }