| 129 | } |
| 130 | |
| 131 | static int |
| 132 | k6_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int *arg) |
| 133 | { |
| 134 | u_int64_t reg; |
| 135 | u_int32_t mtrr; |
| 136 | int error, d; |
| 137 | |
| 138 | switch (*arg) { |
| 139 | case MEMRANGE_SET_UPDATE: |
| 140 | error = k6_mrmake(desc, &mtrr); |
| 141 | if (error) |
| 142 | return (error); |
| 143 | for (d = 0; d < sc->mr_ndesc; d++) { |
| 144 | if (!sc->mr_desc[d].mr_len) { |
| 145 | sc->mr_desc[d] = *desc; |
| 146 | goto out; |
| 147 | } |
| 148 | if (sc->mr_desc[d].mr_base == desc->mr_base && |
| 149 | sc->mr_desc[d].mr_len == desc->mr_len) |
| 150 | return (EEXIST); |
| 151 | } |
| 152 | return (ENOSPC); |
| 153 | case MEMRANGE_SET_REMOVE: |
| 154 | mtrr = 0; |
| 155 | for (d = 0; d < sc->mr_ndesc; d++) |
| 156 | if (sc->mr_desc[d].mr_base == desc->mr_base && |
| 157 | sc->mr_desc[d].mr_len == desc->mr_len) { |
| 158 | bzero(&sc->mr_desc[d], sizeof(sc->mr_desc[d])); |
| 159 | goto out; |
| 160 | } |
| 161 | return (ENOENT); |
| 162 | default: |
| 163 | return (EOPNOTSUPP); |
| 164 | } |
| 165 | out: |
| 166 | disable_intr(); |
| 167 | wbinvd(); |
| 168 | reg = rdmsr(UWCCR); |
| 169 | reg &= ~(0xffffffff << (32 * d)); |
| 170 | reg |= mtrr << (32 * d); |
| 171 | wrmsr(UWCCR, reg); |
| 172 | wbinvd(); |
| 173 | enable_intr(); |
| 174 | |
| 175 | return (0); |
| 176 | } |
| 177 | |
| 178 | static void |
| 179 | k6_mem_drvinit(void *unused) |
nothing calls this directly
no test coverage detected