static void rtas_int_on(struct kvm_cpu *vcpu, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { struct ics_state *ics = vcpu->kvm->arch.icp->ics; uint32_t nr; if ((nargs != 1) || (nret != 1)) { rtas_st(vcpu->kvm, rets, 0, -3); return; } nr = rtas_ld(vcpu->kvm, args, 0); if (!ics_valid_irq(ics, nr)) { rtas_st(vcpu->kvm, rets, 0, -3); return; } /* ME: QEMU wrote xive_msi here, in #if 0. Deleted. */ rtas_st(vcpu->kvm, rets, 0, 0); /* Success */ }
static void rtas_get_xive(struct kvm_cpu *vcpu, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { struct ics_state *ics = vcpu->kvm->arch.icp->ics; uint32_t nr; if ((nargs != 1) || (nret != 3)) { rtas_st(vcpu->kvm, rets, 0, -3); return; } nr = rtas_ld(vcpu->kvm, args, 0); if (!ics_valid_irq(ics, nr)) { rtas_st(vcpu->kvm, rets, 0, -3); return; } rtas_st(vcpu->kvm, rets, 0, 0); /* Success */ rtas_st(vcpu->kvm, rets, 1, ics->irqs[nr - ics->offset].server); rtas_st(vcpu->kvm, rets, 2, ics->irqs[nr - ics->offset].priority); }
static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { ICSState *ics = spapr->icp->ics; uint32_t nr; if ((nargs != 1) || (nret != 3)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } nr = rtas_ld(args, 0); if (!ics_valid_irq(ics, nr)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } rtas_st(rets, 0, RTAS_OUT_SUCCESS); rtas_st(rets, 1, ics->irqs[nr - ics->offset].server); rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority); }
static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { struct ics_state *ics = spapr->icp->ics; uint32_t nr; if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, -3); return; } nr = rtas_ld(args, 0); if (!ics_valid_irq(ics, nr)) { rtas_st(rets, 0, -3); return; } ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff, ics->irqs[nr - ics->offset].priority); rtas_st(rets, 0, 0); /* Success */ }
static void rtas_get_power_level(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { int32_t power_domain; if (nargs != 1 || nret != 2) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } /* we currently only use a single, "live insert" powerdomain for * hotplugged/dlpar'd resources, so the power is always live/full (100) */ power_domain = rtas_ld(args, 0); if (power_domain != -1) { rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); return; } rtas_st(rets, 0, RTAS_OUT_SUCCESS); rtas_st(rets, 1, 100); }
static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { target_ulong parameter = rtas_ld(args, 0); target_ulong ret = RTAS_OUT_NOT_SUPPORTED; switch (parameter) { case DIAGNOSTICS_RUN_MODE: ret = RTAS_OUT_NOT_AUTHORIZED; break; } rtas_st(rets, 0, ret); }
static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { struct tm tm; if (nret != 8) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } qemu_get_timedate(&tm, spapr->rtc_offset); rtas_st(rets, 0, RTAS_OUT_SUCCESS); rtas_st(rets, 1, tm.tm_year + 1900); rtas_st(rets, 2, tm.tm_mon + 1); rtas_st(rets, 3, tm.tm_mday); rtas_st(rets, 4, tm.tm_hour); rtas_st(rets, 5, tm.tm_min); rtas_st(rets, 6, tm.tm_sec); rtas_st(rets, 7, 0); /* we don't do nanoseconds */ }
static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { sPAPRNVRAM *nvram = spapr->nvram; hwaddr offset, buffer, len; int alen; void *membuf; if ((nargs != 3) || (nret != 2)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } if (!nvram) { rtas_st(rets, 0, RTAS_OUT_HW_ERROR); rtas_st(rets, 1, 0); return; } offset = rtas_ld(args, 0); buffer = rtas_ld(args, 1); len = rtas_ld(args, 2); if (((offset + len) < offset) || ((offset + len) > nvram->size)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); rtas_st(rets, 1, 0); return; } membuf = cpu_physical_memory_map(buffer, &len, 1); if (nvram->drive) { alen = bdrv_pread(nvram->drive, offset, membuf, len); } else { assert(nvram->buf); memcpy(membuf, nvram->buf + offset, len); alen = len; } cpu_physical_memory_unmap(membuf, len, 1, len); rtas_st(rets, 0, (alen < len) ? RTAS_OUT_HW_ERROR : RTAS_OUT_SUCCESS); rtas_st(rets, 1, (alen < 0) ? 0 : alen); }
static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { target_ulong parameter = rtas_ld(args, 0); target_ulong ret = RTAS_OUT_NOT_SUPPORTED; switch (parameter) { case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: case RTAS_SYSPARM_UUID: ret = RTAS_OUT_NOT_AUTHORIZED; break; } rtas_st(rets, 0, ret); }
static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { struct tm tm; tm.tm_year = rtas_ld(args, 0) - 1900; tm.tm_mon = rtas_ld(args, 1) - 1; tm.tm_mday = rtas_ld(args, 2); tm.tm_hour = rtas_ld(args, 3); tm.tm_min = rtas_ld(args, 4); tm.tm_sec = rtas_ld(args, 5); /* Just generate a monitor event for the change */ rtc_change_mon_event(&tm); spapr->rtc_offset = qemu_timedate_diff(&tm); rtas_st(rets, 0, RTAS_OUT_SUCCESS); }
static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { target_ulong parameter = rtas_ld(args, 0); target_ulong buffer = rtas_ld(args, 1); target_ulong length = rtas_ld(args, 2); target_ulong ret; switch (parameter) { case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: { char *param_val = g_strdup_printf("MaxEntCap=%d," "DesMem=%llu," "DesProcs=%d," "MaxPlatProcs=%d", max_cpus, current_machine->ram_size / M_BYTE, smp_cpus, max_cpus); ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1); g_free(param_val); break; } case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: { uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED; ret = sysparm_st(buffer, length, ¶m_val, sizeof(param_val)); break; } case RTAS_SYSPARM_UUID: ret = sysparm_st(buffer, length, (unsigned char *)&qemu_uuid, (qemu_uuid_set ? 16 : 0)); break; default: ret = RTAS_OUT_NOT_SUPPORTED; } rtas_st(rets, 0, ret); }
static void rtas_ibm_create_pe_dma_window(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { sPAPRPHBState *sphb; sPAPRTCETable *tcet = NULL; uint32_t addr, page_shift, window_shift, liobn; uint64_t buid, win_addr; int windows; if ((nargs != 5) || (nret != 4)) { goto param_error_exit; } buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); addr = rtas_ld(args, 0); sphb = spapr_pci_find_phb(spapr, buid); if (!sphb || !sphb->ddw_enabled) { goto param_error_exit; } page_shift = rtas_ld(args, 3); window_shift = rtas_ld(args, 4); liobn = spapr_phb_get_free_liobn(sphb); windows = spapr_phb_get_active_win_num(sphb); if (!(sphb->page_size_mask & (1ULL << page_shift)) || (window_shift < page_shift)) { goto param_error_exit; } if (!liobn || !sphb->ddw_enabled || windows == SPAPR_PCI_DMA_MAX_WINDOWS) { goto hw_error_exit; } tcet = spapr_tce_find_by_liobn(liobn); if (!tcet) { goto hw_error_exit; } win_addr = (windows == 0) ? sphb->dma_win_addr : sphb->dma64_win_addr; spapr_tce_table_enable(tcet, page_shift, win_addr, 1ULL << (window_shift - page_shift)); if (!tcet->nb_table) { goto hw_error_exit; } trace_spapr_iommu_ddw_create(buid, addr, 1ULL << page_shift, 1ULL << window_shift, tcet->bus_offset, liobn); rtas_st(rets, 0, RTAS_OUT_SUCCESS); rtas_st(rets, 1, liobn); rtas_st(rets, 2, tcet->bus_offset >> 32); rtas_st(rets, 3, tcet->bus_offset & ((uint32_t) -1)); return; hw_error_exit: rtas_st(rets, 0, RTAS_OUT_HW_ERROR); return; param_error_exit: rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); }