1 /* 2 * QEMU IPMI KCS emulation 3 * 4 * Copyright (c) 2015,2017 Corey Minyard, MontaVista Software, LLC 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include "qemu/osdep.h" 25 #include "migration/vmstate.h" 26 #include "qemu/log.h" 27 #include "qapi/error.h" 28 #include "hw/ipmi/ipmi_kcs.h" 29 30 #define IPMI_KCS_OBF_BIT 0 31 #define IPMI_KCS_IBF_BIT 1 32 #define IPMI_KCS_SMS_ATN_BIT 2 33 #define IPMI_KCS_CD_BIT 3 34 35 #define IPMI_KCS_OBF_MASK (1 << IPMI_KCS_OBF_BIT) 36 #define IPMI_KCS_GET_OBF(d) (((d) >> IPMI_KCS_OBF_BIT) & 0x1) 37 #define IPMI_KCS_SET_OBF(d, v) (d) = (((d) & ~IPMI_KCS_OBF_MASK) | \ 38 (((v) & 1) << IPMI_KCS_OBF_BIT)) 39 #define IPMI_KCS_IBF_MASK (1 << IPMI_KCS_IBF_BIT) 40 #define IPMI_KCS_GET_IBF(d) (((d) >> IPMI_KCS_IBF_BIT) & 0x1) 41 #define IPMI_KCS_SET_IBF(d, v) (d) = (((d) & ~IPMI_KCS_IBF_MASK) | \ 42 (((v) & 1) << IPMI_KCS_IBF_BIT)) 43 #define IPMI_KCS_SMS_ATN_MASK (1 << IPMI_KCS_SMS_ATN_BIT) 44 #define IPMI_KCS_GET_SMS_ATN(d) (((d) >> IPMI_KCS_SMS_ATN_BIT) & 0x1) 45 #define IPMI_KCS_SET_SMS_ATN(d, v) (d) = (((d) & ~IPMI_KCS_SMS_ATN_MASK) | \ 46 (((v) & 1) << IPMI_KCS_SMS_ATN_BIT)) 47 #define IPMI_KCS_CD_MASK (1 << IPMI_KCS_CD_BIT) 48 #define IPMI_KCS_GET_CD(d) (((d) >> IPMI_KCS_CD_BIT) & 0x1) 49 #define IPMI_KCS_SET_CD(d, v) (d) = (((d) & ~IPMI_KCS_CD_MASK) | \ 50 (((v) & 1) << IPMI_KCS_CD_BIT)) 51 52 #define IPMI_KCS_IDLE_STATE 0 53 #define IPMI_KCS_READ_STATE 1 54 #define IPMI_KCS_WRITE_STATE 2 55 #define IPMI_KCS_ERROR_STATE 3 56 57 #define IPMI_KCS_GET_STATE(d) (((d) >> 6) & 0x3) 58 #define IPMI_KCS_SET_STATE(d, v) ((d) = ((d) & ~0xc0) | (((v) & 0x3) << 6)) 59 60 #define IPMI_KCS_ABORT_STATUS_CMD 0x60 61 #define IPMI_KCS_WRITE_START_CMD 0x61 62 #define IPMI_KCS_WRITE_END_CMD 0x62 63 #define IPMI_KCS_READ_CMD 0x68 64 65 #define IPMI_KCS_STATUS_NO_ERR 0x00 66 #define IPMI_KCS_STATUS_ABORTED_ERR 0x01 67 #define IPMI_KCS_STATUS_BAD_CC_ERR 0x02 68 #define IPMI_KCS_STATUS_LENGTH_ERR 0x06 69 70 static void ipmi_kcs_raise_irq(IPMIKCS *ik) 71 { 72 if (ik->use_irq && ik->irqs_enabled && ik->raise_irq) { 73 ik->raise_irq(ik); 74 } 75 } 76 77 static void ipmi_kcs_lower_irq(IPMIKCS *ik) 78 { 79 if (ik->lower_irq) { 80 ik->lower_irq(ik); 81 } 82 } 83 84 #define SET_OBF() \ 85 do { \ 86 IPMI_KCS_SET_OBF(ik->status_reg, 1); \ 87 if (!ik->obf_irq_set) { \ 88 ik->obf_irq_set = 1; \ 89 if (!ik->atn_irq_set) { \ 90 ipmi_kcs_raise_irq(ik); \ 91 } \ 92 } \ 93 } while (0) 94 95 static void ipmi_kcs_signal(IPMIKCS *ik, IPMIInterface *ii) 96 { 97 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 98 99 ik->do_wake = 1; 100 while (ik->do_wake) { 101 ik->do_wake = 0; 102 iic->handle_if_event(ii); 103 } 104 } 105 106 static void ipmi_kcs_handle_event(IPMIInterface *ii) 107 { 108 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 109 IPMIKCS *ik = iic->get_backend_data(ii); 110 111 if (ik->cmd_reg == IPMI_KCS_ABORT_STATUS_CMD) { 112 if (IPMI_KCS_GET_STATE(ik->status_reg) != IPMI_KCS_ERROR_STATE) { 113 ik->waiting_rsp++; /* Invalidate the message */ 114 ik->outmsg[0] = IPMI_KCS_STATUS_ABORTED_ERR; 115 ik->outlen = 1; 116 ik->outpos = 0; 117 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE); 118 SET_OBF(); 119 } 120 goto out; 121 } 122 123 switch (IPMI_KCS_GET_STATE(ik->status_reg)) { 124 case IPMI_KCS_IDLE_STATE: 125 if (ik->cmd_reg == IPMI_KCS_WRITE_START_CMD) { 126 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_WRITE_STATE); 127 ik->cmd_reg = -1; 128 ik->write_end = 0; 129 ik->inlen = 0; 130 SET_OBF(); 131 } 132 break; 133 134 case IPMI_KCS_READ_STATE: 135 handle_read: 136 if (ik->outpos >= ik->outlen) { 137 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_IDLE_STATE); 138 SET_OBF(); 139 } else if (ik->data_in_reg == IPMI_KCS_READ_CMD) { 140 ik->data_out_reg = ik->outmsg[ik->outpos]; 141 ik->outpos++; 142 SET_OBF(); 143 } else { 144 ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR; 145 ik->outlen = 1; 146 ik->outpos = 0; 147 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE); 148 SET_OBF(); 149 goto out; 150 } 151 break; 152 153 case IPMI_KCS_WRITE_STATE: 154 if (ik->data_in_reg != -1) { 155 /* 156 * Don't worry about input overrun here, that will be 157 * handled in the BMC. 158 */ 159 if (ik->inlen < sizeof(ik->inmsg)) { 160 ik->inmsg[ik->inlen] = ik->data_in_reg; 161 } 162 ik->inlen++; 163 } 164 if (ik->write_end) { 165 IPMIBmcClass *bk = IPMI_BMC_GET_CLASS(ik->bmc); 166 ik->outlen = 0; 167 ik->write_end = 0; 168 ik->outpos = 0; 169 bk->handle_command(ik->bmc, ik->inmsg, ik->inlen, sizeof(ik->inmsg), 170 ik->waiting_rsp); 171 return; 172 } else if (ik->cmd_reg == IPMI_KCS_WRITE_END_CMD) { 173 ik->cmd_reg = -1; 174 ik->write_end = 1; 175 } 176 SET_OBF(); 177 break; 178 179 case IPMI_KCS_ERROR_STATE: 180 if (ik->data_in_reg != -1) { 181 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE); 182 ik->data_in_reg = IPMI_KCS_READ_CMD; 183 goto handle_read; 184 } 185 break; 186 } 187 188 if (ik->cmd_reg != -1) { 189 /* Got an invalid command */ 190 ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR; 191 ik->outlen = 1; 192 ik->outpos = 0; 193 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE); 194 } 195 196 out: 197 ik->cmd_reg = -1; 198 ik->data_in_reg = -1; 199 IPMI_KCS_SET_IBF(ik->status_reg, 0); 200 } 201 202 static void ipmi_kcs_handle_rsp(IPMIInterface *ii, uint8_t msg_id, 203 unsigned char *rsp, unsigned int rsp_len) 204 { 205 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 206 IPMIKCS *ik = iic->get_backend_data(ii); 207 208 if (ik->waiting_rsp == msg_id) { 209 ik->waiting_rsp++; 210 if (rsp_len > sizeof(ik->outmsg)) { 211 ik->outmsg[0] = rsp[0]; 212 ik->outmsg[1] = rsp[1]; 213 ik->outmsg[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES; 214 ik->outlen = 3; 215 } else { 216 memcpy(ik->outmsg, rsp, rsp_len); 217 ik->outlen = rsp_len; 218 } 219 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE); 220 ik->data_in_reg = IPMI_KCS_READ_CMD; 221 ipmi_kcs_signal(ik, ii); 222 } 223 } 224 225 226 static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr addr, unsigned size) 227 { 228 IPMIInterface *ii = opaque; 229 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 230 IPMIKCS *ik = iic->get_backend_data(ii); 231 uint32_t ret; 232 233 switch (addr & ik->size_mask) { 234 case 0: 235 ret = ik->data_out_reg; 236 IPMI_KCS_SET_OBF(ik->status_reg, 0); 237 if (ik->obf_irq_set) { 238 ik->obf_irq_set = 0; 239 if (!ik->atn_irq_set) { 240 ipmi_kcs_lower_irq(ik); 241 } 242 } 243 break; 244 245 case 1: 246 ret = ik->status_reg; 247 if (ik->atn_irq_set) { 248 ik->atn_irq_set = 0; 249 if (!ik->obf_irq_set) { 250 ipmi_kcs_lower_irq(ik); 251 } 252 } 253 break; 254 255 default: 256 ret = 0xff; 257 } 258 return ret; 259 } 260 261 static void ipmi_kcs_ioport_write(void *opaque, hwaddr addr, uint64_t val, 262 unsigned size) 263 { 264 IPMIInterface *ii = opaque; 265 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 266 IPMIKCS *ik = iic->get_backend_data(ii); 267 268 if (IPMI_KCS_GET_IBF(ik->status_reg)) { 269 return; 270 } 271 272 switch (addr & ik->size_mask) { 273 case 0: 274 ik->data_in_reg = val; 275 break; 276 277 case 1: 278 ik->cmd_reg = val; 279 break; 280 281 default: 282 /* Ignore. */ 283 break; 284 } 285 IPMI_KCS_SET_IBF(ik->status_reg, 1); 286 ipmi_kcs_signal(ik, ii); 287 } 288 289 const MemoryRegionOps ipmi_kcs_io_ops = { 290 .read = ipmi_kcs_ioport_read, 291 .write = ipmi_kcs_ioport_write, 292 .impl = { 293 .min_access_size = 1, 294 .max_access_size = 1, 295 }, 296 .endianness = DEVICE_LITTLE_ENDIAN, 297 }; 298 299 static void ipmi_kcs_set_atn(IPMIInterface *ii, int val, int irq) 300 { 301 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 302 IPMIKCS *ik = iic->get_backend_data(ii); 303 304 IPMI_KCS_SET_SMS_ATN(ik->status_reg, val); 305 if (val) { 306 if (irq && !ik->atn_irq_set) { 307 ik->atn_irq_set = 1; 308 if (!ik->obf_irq_set) { 309 ipmi_kcs_raise_irq(ik); 310 } 311 } 312 } else { 313 if (ik->atn_irq_set) { 314 ik->atn_irq_set = 0; 315 if (!ik->obf_irq_set) { 316 ipmi_kcs_lower_irq(ik); 317 } 318 } 319 } 320 } 321 322 static void ipmi_kcs_set_irq_enable(IPMIInterface *ii, int val) 323 { 324 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 325 IPMIKCS *ik = iic->get_backend_data(ii); 326 327 ik->irqs_enabled = val; 328 } 329 330 /* min_size must be a power of 2. */ 331 static void ipmi_kcs_init(IPMIInterface *ii, unsigned int min_size, 332 Error **errp) 333 { 334 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 335 IPMIKCS *ik = iic->get_backend_data(ii); 336 337 if (min_size == 0) { 338 min_size = 2; 339 } 340 ik->size_mask = min_size - 1; 341 ik->io_length = 2; 342 memory_region_init_io(&ik->io, NULL, &ipmi_kcs_io_ops, ii, "ipmi-kcs", 343 min_size); 344 } 345 346 int ipmi_kcs_vmstate_post_load(void *opaque, int version) 347 { 348 IPMIKCS *ik = opaque; 349 350 /* Make sure all the values are sane. */ 351 if (ik->outpos >= MAX_IPMI_MSG_SIZE || ik->outlen >= MAX_IPMI_MSG_SIZE || 352 ik->outpos >= ik->outlen) { 353 qemu_log_mask(LOG_GUEST_ERROR, 354 "ipmi:kcs: vmstate transfer received bad out values: %d %d\n", 355 ik->outpos, ik->outlen); 356 ik->outpos = 0; 357 ik->outlen = 0; 358 } 359 360 if (ik->inlen >= MAX_IPMI_MSG_SIZE) { 361 qemu_log_mask(LOG_GUEST_ERROR, 362 "ipmi:kcs: vmstate transfer received bad in value: %d\n", 363 ik->inlen); 364 ik->inlen = 0; 365 } 366 367 return 0; 368 } 369 370 static bool vmstate_kcs_before_version2(void *opaque, int version) 371 { 372 return version <= 1; 373 } 374 375 const VMStateDescription vmstate_IPMIKCS = { 376 .name = TYPE_IPMI_INTERFACE_PREFIX "kcs", 377 .version_id = 2, 378 .minimum_version_id = 1, 379 .post_load = ipmi_kcs_vmstate_post_load, 380 .fields = (const VMStateField[]) { 381 VMSTATE_BOOL(obf_irq_set, IPMIKCS), 382 VMSTATE_BOOL(atn_irq_set, IPMIKCS), 383 VMSTATE_UNUSED_TEST(vmstate_kcs_before_version2, 1), /* Was use_irq */ 384 VMSTATE_BOOL(irqs_enabled, IPMIKCS), 385 VMSTATE_UINT32(outpos, IPMIKCS), 386 VMSTATE_UINT32_V(outlen, IPMIKCS, 2), 387 VMSTATE_UINT8_ARRAY(outmsg, IPMIKCS, MAX_IPMI_MSG_SIZE), 388 VMSTATE_UINT32_V(inlen, IPMIKCS, 2), 389 VMSTATE_UINT8_ARRAY(inmsg, IPMIKCS, MAX_IPMI_MSG_SIZE), 390 VMSTATE_BOOL(write_end, IPMIKCS), 391 VMSTATE_UINT8(status_reg, IPMIKCS), 392 VMSTATE_UINT8(data_out_reg, IPMIKCS), 393 VMSTATE_INT16(data_in_reg, IPMIKCS), 394 VMSTATE_INT16(cmd_reg, IPMIKCS), 395 VMSTATE_UINT8(waiting_rsp, IPMIKCS), 396 VMSTATE_END_OF_LIST() 397 } 398 }; 399 400 void ipmi_kcs_get_fwinfo(IPMIKCS *ik, IPMIFwInfo *info) 401 { 402 info->interface_name = "kcs"; 403 info->interface_type = IPMI_SMBIOS_KCS; 404 info->ipmi_spec_major_revision = 2; 405 info->ipmi_spec_minor_revision = 0; 406 info->ipmi_channel_protocol = IPMI_CHANNEL_PROTOCOL_KCS; 407 info->base_address = ik->io_base; 408 info->i2c_slave_address = ik->bmc->slave_addr; 409 info->register_length = ik->io_length; 410 info->register_spacing = 1; 411 info->memspace = IPMI_MEMSPACE_IO; 412 info->irq_type = IPMI_LEVEL_IRQ; 413 } 414 415 void ipmi_kcs_class_init(IPMIInterfaceClass *iic) 416 { 417 iic->init = ipmi_kcs_init; 418 iic->set_atn = ipmi_kcs_set_atn; 419 iic->handle_rsp = ipmi_kcs_handle_rsp; 420 iic->handle_if_event = ipmi_kcs_handle_event; 421 iic->set_irq_enable = ipmi_kcs_set_irq_enable; 422 } 423