1 /* 2 * QEMU ISA IPMI KCS emulation 3 * 4 * Copyright (c) 2015 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 25 #include "qemu/osdep.h" 26 #include "qemu/log.h" 27 #include "qemu/module.h" 28 #include "qapi/error.h" 29 #include "hw/hw.h" 30 #include "hw/ipmi/ipmi.h" 31 #include "hw/isa/isa.h" 32 33 #define IPMI_KCS_OBF_BIT 0 34 #define IPMI_KCS_IBF_BIT 1 35 #define IPMI_KCS_SMS_ATN_BIT 2 36 #define IPMI_KCS_CD_BIT 3 37 38 #define IPMI_KCS_OBF_MASK (1 << IPMI_KCS_OBF_BIT) 39 #define IPMI_KCS_GET_OBF(d) (((d) >> IPMI_KCS_OBF_BIT) & 0x1) 40 #define IPMI_KCS_SET_OBF(d, v) (d) = (((d) & ~IPMI_KCS_OBF_MASK) | \ 41 (((v) & 1) << IPMI_KCS_OBF_BIT)) 42 #define IPMI_KCS_IBF_MASK (1 << IPMI_KCS_IBF_BIT) 43 #define IPMI_KCS_GET_IBF(d) (((d) >> IPMI_KCS_IBF_BIT) & 0x1) 44 #define IPMI_KCS_SET_IBF(d, v) (d) = (((d) & ~IPMI_KCS_IBF_MASK) | \ 45 (((v) & 1) << IPMI_KCS_IBF_BIT)) 46 #define IPMI_KCS_SMS_ATN_MASK (1 << IPMI_KCS_SMS_ATN_BIT) 47 #define IPMI_KCS_GET_SMS_ATN(d) (((d) >> IPMI_KCS_SMS_ATN_BIT) & 0x1) 48 #define IPMI_KCS_SET_SMS_ATN(d, v) (d) = (((d) & ~IPMI_KCS_SMS_ATN_MASK) | \ 49 (((v) & 1) << IPMI_KCS_SMS_ATN_BIT)) 50 #define IPMI_KCS_CD_MASK (1 << IPMI_KCS_CD_BIT) 51 #define IPMI_KCS_GET_CD(d) (((d) >> IPMI_KCS_CD_BIT) & 0x1) 52 #define IPMI_KCS_SET_CD(d, v) (d) = (((d) & ~IPMI_KCS_CD_MASK) | \ 53 (((v) & 1) << IPMI_KCS_CD_BIT)) 54 55 #define IPMI_KCS_IDLE_STATE 0 56 #define IPMI_KCS_READ_STATE 1 57 #define IPMI_KCS_WRITE_STATE 2 58 #define IPMI_KCS_ERROR_STATE 3 59 60 #define IPMI_KCS_GET_STATE(d) (((d) >> 6) & 0x3) 61 #define IPMI_KCS_SET_STATE(d, v) ((d) = ((d) & ~0xc0) | (((v) & 0x3) << 6)) 62 63 #define IPMI_KCS_ABORT_STATUS_CMD 0x60 64 #define IPMI_KCS_WRITE_START_CMD 0x61 65 #define IPMI_KCS_WRITE_END_CMD 0x62 66 #define IPMI_KCS_READ_CMD 0x68 67 68 #define IPMI_KCS_STATUS_NO_ERR 0x00 69 #define IPMI_KCS_STATUS_ABORTED_ERR 0x01 70 #define IPMI_KCS_STATUS_BAD_CC_ERR 0x02 71 #define IPMI_KCS_STATUS_LENGTH_ERR 0x06 72 73 typedef struct IPMIKCS { 74 IPMIBmc *bmc; 75 76 bool do_wake; 77 78 qemu_irq irq; 79 80 uint32_t io_base; 81 unsigned long io_length; 82 MemoryRegion io; 83 84 bool obf_irq_set; 85 bool atn_irq_set; 86 bool use_irq; 87 bool irqs_enabled; 88 89 uint8_t outmsg[MAX_IPMI_MSG_SIZE]; 90 uint32_t outpos; 91 uint32_t outlen; 92 93 uint8_t inmsg[MAX_IPMI_MSG_SIZE]; 94 uint32_t inlen; 95 bool write_end; 96 97 uint8_t status_reg; 98 uint8_t data_out_reg; 99 100 int16_t data_in_reg; /* -1 means not written */ 101 int16_t cmd_reg; 102 103 /* 104 * This is a response number that we send with the command to make 105 * sure that the response matches the command. 106 */ 107 uint8_t waiting_rsp; 108 } IPMIKCS; 109 110 #define SET_OBF() \ 111 do { \ 112 IPMI_KCS_SET_OBF(ik->status_reg, 1); \ 113 if (ik->use_irq && ik->irqs_enabled && !ik->obf_irq_set) { \ 114 ik->obf_irq_set = 1; \ 115 if (!ik->atn_irq_set) { \ 116 qemu_irq_raise(ik->irq); \ 117 } \ 118 } \ 119 } while (0) 120 121 static void ipmi_kcs_signal(IPMIKCS *ik, IPMIInterface *ii) 122 { 123 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 124 125 ik->do_wake = 1; 126 while (ik->do_wake) { 127 ik->do_wake = 0; 128 iic->handle_if_event(ii); 129 } 130 } 131 132 static void ipmi_kcs_handle_event(IPMIInterface *ii) 133 { 134 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 135 IPMIKCS *ik = iic->get_backend_data(ii); 136 137 if (ik->cmd_reg == IPMI_KCS_ABORT_STATUS_CMD) { 138 if (IPMI_KCS_GET_STATE(ik->status_reg) != IPMI_KCS_ERROR_STATE) { 139 ik->waiting_rsp++; /* Invalidate the message */ 140 ik->outmsg[0] = IPMI_KCS_STATUS_ABORTED_ERR; 141 ik->outlen = 1; 142 ik->outpos = 0; 143 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE); 144 SET_OBF(); 145 } 146 goto out; 147 } 148 149 switch (IPMI_KCS_GET_STATE(ik->status_reg)) { 150 case IPMI_KCS_IDLE_STATE: 151 if (ik->cmd_reg == IPMI_KCS_WRITE_START_CMD) { 152 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_WRITE_STATE); 153 ik->cmd_reg = -1; 154 ik->write_end = 0; 155 ik->inlen = 0; 156 SET_OBF(); 157 } 158 break; 159 160 case IPMI_KCS_READ_STATE: 161 handle_read: 162 if (ik->outpos >= ik->outlen) { 163 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_IDLE_STATE); 164 SET_OBF(); 165 } else if (ik->data_in_reg == IPMI_KCS_READ_CMD) { 166 ik->data_out_reg = ik->outmsg[ik->outpos]; 167 ik->outpos++; 168 SET_OBF(); 169 } else { 170 ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR; 171 ik->outlen = 1; 172 ik->outpos = 0; 173 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE); 174 SET_OBF(); 175 goto out; 176 } 177 break; 178 179 case IPMI_KCS_WRITE_STATE: 180 if (ik->data_in_reg != -1) { 181 /* 182 * Don't worry about input overrun here, that will be 183 * handled in the BMC. 184 */ 185 if (ik->inlen < sizeof(ik->inmsg)) { 186 ik->inmsg[ik->inlen] = ik->data_in_reg; 187 } 188 ik->inlen++; 189 } 190 if (ik->write_end) { 191 IPMIBmcClass *bk = IPMI_BMC_GET_CLASS(ik->bmc); 192 ik->outlen = 0; 193 ik->write_end = 0; 194 ik->outpos = 0; 195 bk->handle_command(ik->bmc, ik->inmsg, ik->inlen, sizeof(ik->inmsg), 196 ik->waiting_rsp); 197 goto out_noibf; 198 } else if (ik->cmd_reg == IPMI_KCS_WRITE_END_CMD) { 199 ik->cmd_reg = -1; 200 ik->write_end = 1; 201 } 202 SET_OBF(); 203 break; 204 205 case IPMI_KCS_ERROR_STATE: 206 if (ik->data_in_reg != -1) { 207 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE); 208 ik->data_in_reg = IPMI_KCS_READ_CMD; 209 goto handle_read; 210 } 211 break; 212 } 213 214 if (ik->cmd_reg != -1) { 215 /* Got an invalid command */ 216 ik->outmsg[0] = IPMI_KCS_STATUS_BAD_CC_ERR; 217 ik->outlen = 1; 218 ik->outpos = 0; 219 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_ERROR_STATE); 220 } 221 222 out: 223 ik->cmd_reg = -1; 224 ik->data_in_reg = -1; 225 IPMI_KCS_SET_IBF(ik->status_reg, 0); 226 out_noibf: 227 return; 228 } 229 230 static void ipmi_kcs_handle_rsp(IPMIInterface *ii, uint8_t msg_id, 231 unsigned char *rsp, unsigned int rsp_len) 232 { 233 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 234 IPMIKCS *ik = iic->get_backend_data(ii); 235 236 if (ik->waiting_rsp == msg_id) { 237 ik->waiting_rsp++; 238 if (rsp_len > sizeof(ik->outmsg)) { 239 ik->outmsg[0] = rsp[0]; 240 ik->outmsg[1] = rsp[1]; 241 ik->outmsg[2] = IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES; 242 ik->outlen = 3; 243 } else { 244 memcpy(ik->outmsg, rsp, rsp_len); 245 ik->outlen = rsp_len; 246 } 247 IPMI_KCS_SET_STATE(ik->status_reg, IPMI_KCS_READ_STATE); 248 ik->data_in_reg = IPMI_KCS_READ_CMD; 249 ipmi_kcs_signal(ik, ii); 250 } 251 } 252 253 254 static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr addr, unsigned size) 255 { 256 IPMIInterface *ii = opaque; 257 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 258 IPMIKCS *ik = iic->get_backend_data(ii); 259 uint32_t ret; 260 261 switch (addr & 1) { 262 case 0: 263 ret = ik->data_out_reg; 264 IPMI_KCS_SET_OBF(ik->status_reg, 0); 265 if (ik->obf_irq_set) { 266 ik->obf_irq_set = 0; 267 if (!ik->atn_irq_set) { 268 qemu_irq_lower(ik->irq); 269 } 270 } 271 break; 272 case 1: 273 ret = ik->status_reg; 274 if (ik->atn_irq_set) { 275 ik->atn_irq_set = 0; 276 if (!ik->obf_irq_set) { 277 qemu_irq_lower(ik->irq); 278 } 279 } 280 break; 281 } 282 return ret; 283 } 284 285 static void ipmi_kcs_ioport_write(void *opaque, hwaddr addr, uint64_t val, 286 unsigned size) 287 { 288 IPMIInterface *ii = opaque; 289 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 290 IPMIKCS *ik = iic->get_backend_data(ii); 291 292 if (IPMI_KCS_GET_IBF(ik->status_reg)) { 293 return; 294 } 295 296 switch (addr & 1) { 297 case 0: 298 ik->data_in_reg = val; 299 break; 300 301 case 1: 302 ik->cmd_reg = val; 303 break; 304 } 305 IPMI_KCS_SET_IBF(ik->status_reg, 1); 306 ipmi_kcs_signal(ik, ii); 307 } 308 309 const MemoryRegionOps ipmi_kcs_io_ops = { 310 .read = ipmi_kcs_ioport_read, 311 .write = ipmi_kcs_ioport_write, 312 .impl = { 313 .min_access_size = 1, 314 .max_access_size = 1, 315 }, 316 .endianness = DEVICE_LITTLE_ENDIAN, 317 }; 318 319 static void ipmi_kcs_set_atn(IPMIInterface *ii, int val, int irq) 320 { 321 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 322 IPMIKCS *ik = iic->get_backend_data(ii); 323 324 IPMI_KCS_SET_SMS_ATN(ik->status_reg, val); 325 if (val) { 326 if (irq && !ik->atn_irq_set && ik->use_irq && ik->irqs_enabled) { 327 ik->atn_irq_set = 1; 328 if (!ik->obf_irq_set) { 329 qemu_irq_raise(ik->irq); 330 } 331 } 332 } else { 333 if (ik->atn_irq_set) { 334 ik->atn_irq_set = 0; 335 if (!ik->obf_irq_set) { 336 qemu_irq_lower(ik->irq); 337 } 338 } 339 } 340 } 341 342 static void ipmi_kcs_set_irq_enable(IPMIInterface *ii, int val) 343 { 344 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 345 IPMIKCS *ik = iic->get_backend_data(ii); 346 347 ik->irqs_enabled = val; 348 } 349 350 static void ipmi_kcs_init(IPMIInterface *ii, Error **errp) 351 { 352 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 353 IPMIKCS *ik = iic->get_backend_data(ii); 354 355 ik->io_length = 2; 356 memory_region_init_io(&ik->io, NULL, &ipmi_kcs_io_ops, ii, "ipmi-kcs", 2); 357 } 358 359 #define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs" 360 #define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \ 361 TYPE_ISA_IPMI_KCS) 362 363 typedef struct ISAIPMIKCSDevice { 364 ISADevice dev; 365 int32_t isairq; 366 IPMIKCS kcs; 367 uint32_t uuid; 368 } ISAIPMIKCSDevice; 369 370 static void ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info) 371 { 372 ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii); 373 374 info->interface_name = "kcs"; 375 info->interface_type = IPMI_SMBIOS_KCS; 376 info->ipmi_spec_major_revision = 2; 377 info->ipmi_spec_minor_revision = 0; 378 info->base_address = iik->kcs.io_base; 379 info->i2c_slave_address = iik->kcs.bmc->slave_addr; 380 info->register_length = iik->kcs.io_length; 381 info->register_spacing = 1; 382 info->memspace = IPMI_MEMSPACE_IO; 383 info->irq_type = IPMI_LEVEL_IRQ; 384 info->interrupt_number = iik->isairq; 385 info->uuid = iik->uuid; 386 } 387 388 static void ipmi_kcs_class_init(IPMIInterfaceClass *iic) 389 { 390 iic->init = ipmi_kcs_init; 391 iic->set_atn = ipmi_kcs_set_atn; 392 iic->handle_rsp = ipmi_kcs_handle_rsp; 393 iic->handle_if_event = ipmi_kcs_handle_event; 394 iic->set_irq_enable = ipmi_kcs_set_irq_enable; 395 iic->get_fwinfo = ipmi_kcs_get_fwinfo; 396 } 397 398 static void ipmi_isa_realize(DeviceState *dev, Error **errp) 399 { 400 ISADevice *isadev = ISA_DEVICE(dev); 401 ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(dev); 402 IPMIInterface *ii = IPMI_INTERFACE(dev); 403 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); 404 405 if (!iik->kcs.bmc) { 406 error_setg(errp, "IPMI device requires a bmc attribute to be set"); 407 return; 408 } 409 410 iik->uuid = ipmi_next_uuid(); 411 412 iik->kcs.bmc->intf = ii; 413 414 iic->init(ii, errp); 415 if (*errp) 416 return; 417 418 if (iik->isairq > 0) { 419 isa_init_irq(isadev, &iik->kcs.irq, iik->isairq); 420 iik->kcs.use_irq = 1; 421 } 422 423 qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length); 424 425 isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base); 426 } 427 428 static int ipmi_kcs_vmstate_post_load(void *opaque, int version) 429 { 430 IPMIKCS *ik = opaque; 431 432 /* Make sure all the values are sane. */ 433 if (ik->outpos >= MAX_IPMI_MSG_SIZE || ik->outlen >= MAX_IPMI_MSG_SIZE || 434 ik->outpos >= ik->outlen) { 435 qemu_log_mask(LOG_GUEST_ERROR, 436 "ipmi:kcs: vmstate transfer received bad out values: %d %d\n", 437 ik->outpos, ik->outlen); 438 ik->outpos = 0; 439 ik->outlen = 0; 440 } 441 442 if (ik->inlen >= MAX_IPMI_MSG_SIZE) { 443 qemu_log_mask(LOG_GUEST_ERROR, 444 "ipmi:kcs: vmstate transfer received bad in value: %d\n", 445 ik->inlen); 446 ik->inlen = 0; 447 } 448 449 return 0; 450 } 451 452 static bool vmstate_kcs_before_version2(void *opaque, int version) 453 { 454 return version <= 1; 455 } 456 457 static const VMStateDescription vmstate_IPMIKCS = { 458 .name = TYPE_IPMI_INTERFACE_PREFIX "kcs", 459 .version_id = 2, 460 .minimum_version_id = 1, 461 .post_load = ipmi_kcs_vmstate_post_load, 462 .fields = (VMStateField[]) { 463 VMSTATE_BOOL(obf_irq_set, IPMIKCS), 464 VMSTATE_BOOL(atn_irq_set, IPMIKCS), 465 VMSTATE_UNUSED_TEST(vmstate_kcs_before_version2, 1), /* Was use_irq */ 466 VMSTATE_BOOL(irqs_enabled, IPMIKCS), 467 VMSTATE_UINT32(outpos, IPMIKCS), 468 VMSTATE_UINT32_V(outlen, IPMIKCS, 2), 469 VMSTATE_UINT8_ARRAY(outmsg, IPMIKCS, MAX_IPMI_MSG_SIZE), 470 VMSTATE_UINT32_V(inlen, IPMIKCS, 2), 471 VMSTATE_UINT8_ARRAY(inmsg, IPMIKCS, MAX_IPMI_MSG_SIZE), 472 VMSTATE_BOOL(write_end, IPMIKCS), 473 VMSTATE_UINT8(status_reg, IPMIKCS), 474 VMSTATE_UINT8(data_out_reg, IPMIKCS), 475 VMSTATE_INT16(data_in_reg, IPMIKCS), 476 VMSTATE_INT16(cmd_reg, IPMIKCS), 477 VMSTATE_UINT8(waiting_rsp, IPMIKCS), 478 VMSTATE_END_OF_LIST() 479 } 480 }; 481 482 static const VMStateDescription vmstate_ISAIPMIKCSDevice = { 483 .name = TYPE_IPMI_INTERFACE, 484 .version_id = 2, 485 .minimum_version_id = 1, 486 .fields = (VMStateField[]) { 487 VMSTATE_VSTRUCT_TEST(kcs, ISAIPMIKCSDevice, vmstate_kcs_before_version2, 488 0, vmstate_IPMIKCS, IPMIKCS, 1), 489 VMSTATE_VSTRUCT_V(kcs, ISAIPMIKCSDevice, 2, vmstate_IPMIKCS, 490 IPMIKCS, 2), 491 VMSTATE_END_OF_LIST() 492 } 493 }; 494 495 static void isa_ipmi_kcs_init(Object *obj) 496 { 497 ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(obj); 498 499 ipmi_bmc_find_and_link(obj, (Object **) &iik->kcs.bmc); 500 501 /* 502 * Version 1 had an incorrect name, it clashed with the BT 503 * IPMI device, so receive it, but transmit a different 504 * version. 505 */ 506 vmstate_register(NULL, 0, &vmstate_ISAIPMIKCSDevice, iik); 507 } 508 509 static void *isa_ipmi_kcs_get_backend_data(IPMIInterface *ii) 510 { 511 ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii); 512 513 return &iik->kcs; 514 } 515 516 static Property ipmi_isa_properties[] = { 517 DEFINE_PROP_UINT32("ioport", ISAIPMIKCSDevice, kcs.io_base, 0xca2), 518 DEFINE_PROP_INT32("irq", ISAIPMIKCSDevice, isairq, 5), 519 DEFINE_PROP_END_OF_LIST(), 520 }; 521 522 static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data) 523 { 524 DeviceClass *dc = DEVICE_CLASS(oc); 525 IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc); 526 527 dc->realize = ipmi_isa_realize; 528 dc->props = ipmi_isa_properties; 529 530 iic->get_backend_data = isa_ipmi_kcs_get_backend_data; 531 ipmi_kcs_class_init(iic); 532 } 533 534 static const TypeInfo isa_ipmi_kcs_info = { 535 .name = TYPE_ISA_IPMI_KCS, 536 .parent = TYPE_ISA_DEVICE, 537 .instance_size = sizeof(ISAIPMIKCSDevice), 538 .instance_init = isa_ipmi_kcs_init, 539 .class_init = isa_ipmi_kcs_class_init, 540 .interfaces = (InterfaceInfo[]) { 541 { TYPE_IPMI_INTERFACE }, 542 { } 543 } 544 }; 545 546 static void ipmi_register_types(void) 547 { 548 type_register_static(&isa_ipmi_kcs_info); 549 } 550 551 type_init(ipmi_register_types) 552