int sclp_service_call(uint32_t sccb, uint64_t code) { int r = 0; SCCB work_sccb; hwaddr sccb_len = sizeof(SCCB); /* first some basic checks on program checks */ if (cpu_physical_memory_is_io(sccb)) { r = -PGM_ADDRESSING; goto out; } if (sccb & ~0x7ffffff8ul) { r = -PGM_SPECIFICATION; goto out; } /* * we want to work on a private copy of the sccb, to prevent guests * from playing dirty tricks by modifying the memory content after * the host has checked the values */ cpu_physical_memory_read(sccb, &work_sccb, sccb_len); /* Valid sccb sizes */ if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader) || be16_to_cpu(work_sccb.h.length) > SCCB_SIZE) { r = -PGM_SPECIFICATION; goto out; } sclp_execute((SCCB *)&work_sccb, code); cpu_physical_memory_write(sccb, &work_sccb, be16_to_cpu(work_sccb.h.length)); sclp_service_interrupt(sccb); out: return r; }