static PARSER_CONTEXT * parser_init_guts(u64 addr, u32 bytes, BOOL isLocal, BOOL hasStandardPayloadHeader, BOOL *tryAgain) { int allocbytes = sizeof(PARSER_CONTEXT) + bytes; PARSER_CONTEXT *rc = NULL; PARSER_CONTEXT *ctx = NULL; struct memregion *rgn = NULL; struct spar_controlvm_parameters_header *phdr = NULL; if (tryAgain) *tryAgain = FALSE; if (!hasStandardPayloadHeader) /* alloc and 0 extra byte to ensure payload is * '\0'-terminated */ allocbytes++; if ((Controlvm_Payload_Bytes_Buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { ERRDRV("%s (%s:%d) - prevented allocation of %d bytes to prevent exceeding throttling max (%d)", __func__, __FILE__, __LINE__, allocbytes, MAX_CONTROLVM_PAYLOAD_BYTES); if (tryAgain) *tryAgain = TRUE; rc = NULL; goto Away; } ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); if (ctx == NULL) { ERRDRV("%s (%s:%d) - failed to allocate %d bytes", __func__, __FILE__, __LINE__, allocbytes); if (tryAgain) *tryAgain = TRUE; rc = NULL; goto Away; } ctx->allocbytes = allocbytes; ctx->param_bytes = bytes; ctx->curr = NULL; ctx->bytes_remaining = 0; ctx->byte_stream = FALSE; if (isLocal) { void *p; if (addr > virt_to_phys(high_memory - 1)) { ERRDRV("%s - bad local address (0x%-16.16Lx for %lu)", __func__, (unsigned long long) addr, (ulong) bytes); rc = NULL; goto Away; } p = __va((ulong) (addr)); memcpy(ctx->data, p, bytes); } else { rgn = visor_memregion_create(addr, bytes); if (!rgn) { rc = NULL; goto Away; } if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { rc = NULL; goto Away; } } if (!hasStandardPayloadHeader) { ctx->byte_stream = TRUE; rc = ctx; goto Away; } phdr = (struct spar_controlvm_parameters_header *)(ctx->data); if (phdr->total_length != bytes) { ERRDRV("%s - bad total length %lu (should be %lu)", __func__, (ulong) (phdr->total_length), (ulong) (bytes)); rc = NULL; goto Away; } if (phdr->total_length < phdr->header_length) { ERRDRV("%s - total length < header length (%lu < %lu)", __func__, (ulong) (phdr->total_length), (ulong) (phdr->header_length)); rc = NULL; goto Away; } if (phdr->header_length < sizeof(struct spar_controlvm_parameters_header)) { ERRDRV("%s - header is too small (%lu < %lu)", __func__, (ulong) (phdr->header_length), (ulong)(sizeof( struct spar_controlvm_parameters_header))); rc = NULL; goto Away; } rc = ctx; Away: if (rgn) { visor_memregion_destroy(rgn); rgn = NULL; } if (rc) Controlvm_Payload_Bytes_Buffered += ctx->param_bytes; else { if (ctx) { parser_done(ctx); ctx = NULL; } } return rc; }
/* Creates the VISORCHANNEL abstraction for a data area in memory, but does * NOT modify this data area. */ static VISORCHANNEL * visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes, VISORCHANNEL *parent, ulong off, uuid_le guid, BOOL needs_lock) { VISORCHANNEL *p = NULL; void *rc = NULL; p = kmalloc(sizeof(VISORCHANNEL), GFP_KERNEL|__GFP_NORETRY); if (p == NULL) { ERRDRV("allocation failed: (status=0)\n"); rc = NULL; goto Away; } p->memregion = NULL; p->needs_lock = needs_lock; spin_lock_init(&p->insert_lock); spin_lock_init(&p->remove_lock); /* prepare chan_hdr (abstraction to read/write channel memory) */ if (parent == NULL) p->memregion = visor_memregion_create(physaddr, sizeof(CHANNEL_HEADER)); else p->memregion = visor_memregion_create_overlapped(parent->memregion, off, sizeof(CHANNEL_HEADER)); if (p->memregion == NULL) { ERRDRV("visor_memregion_create failed failed: (status=0)\n"); rc = NULL; goto Away; } if (visor_memregion_read(p->memregion, 0, &p->chan_hdr, sizeof(CHANNEL_HEADER)) < 0) { ERRDRV("visor_memregion_read failed: (status=0)\n"); rc = NULL; goto Away; } if (channelBytes == 0) /* we had better be a CLIENT of this channel */ channelBytes = (ulong) p->chan_hdr.Size; if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) /* we had better be a CLIENT of this channel */ guid = p->chan_hdr.Type; if (visor_memregion_resize(p->memregion, channelBytes) < 0) { ERRDRV("visor_memregion_resize failed: (status=0)\n"); rc = NULL; goto Away; } p->size = channelBytes; p->guid = guid; rc = p; Away: if (rc == NULL) { if (p != NULL) { visorchannel_destroy(p); p = NULL; } } return rc; }
static struct parser_context * parser_init_guts(u64 addr, u32 bytes, BOOL local, BOOL standard_payload_header, BOOL *retry) { int allocbytes = sizeof(struct parser_context) + bytes; struct parser_context *rc = NULL; struct parser_context *ctx = NULL; struct memregion *rgn = NULL; struct spar_controlvm_parameters_header *phdr = NULL; if (retry) *retry = FALSE; if (!standard_payload_header) /* alloc and 0 extra byte to ensure payload is * '\0'-terminated */ allocbytes++; if ((controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { if (retry) *retry = TRUE; rc = NULL; goto cleanup; } ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); if (!ctx) { if (retry) *retry = TRUE; rc = NULL; goto cleanup; } ctx->allocbytes = allocbytes; ctx->param_bytes = bytes; ctx->curr = NULL; ctx->bytes_remaining = 0; ctx->byte_stream = FALSE; if (local) { void *p; if (addr > virt_to_phys(high_memory - 1)) { rc = NULL; goto cleanup; } p = __va((ulong) (addr)); memcpy(ctx->data, p, bytes); } else { rgn = visor_memregion_create(addr, bytes); if (!rgn) { rc = NULL; goto cleanup; } if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { rc = NULL; goto cleanup; } } if (!standard_payload_header) { ctx->byte_stream = TRUE; rc = ctx; goto cleanup; } phdr = (struct spar_controlvm_parameters_header *)(ctx->data); if (phdr->total_length != bytes) { rc = NULL; goto cleanup; } if (phdr->total_length < phdr->header_length) { rc = NULL; goto cleanup; } if (phdr->header_length < sizeof(struct spar_controlvm_parameters_header)) { rc = NULL; goto cleanup; } rc = ctx; cleanup: if (rgn) { visor_memregion_destroy(rgn); rgn = NULL; } if (rc) { controlvm_payload_bytes_buffered += ctx->param_bytes; } else { if (ctx) { parser_done(ctx); ctx = NULL; } } return rc; }