drivers/virt/coco/guest/tsm-mr.c

Source file repositories/reference/linux-study-clean/drivers/virt/coco/guest/tsm-mr.c

File Facts

System
Linux kernel
Corpus path
drivers/virt/coco/guest/tsm-mr.c
Extension
.c
Size
7116 bytes
Lines
252
Domain
Driver Families
Bucket
drivers/virt
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct tm_context {
	struct rw_semaphore rwsem;
	struct attribute_group agrp;
	const struct tsm_measurements *tm;
	bool in_sync;
	struct bin_attribute mrs[];
};

static ssize_t tm_digest_read(struct file *filp, struct kobject *kobj,
			      const struct bin_attribute *attr, char *buffer,
			      loff_t off, size_t count)
{
	struct tm_context *ctx;
	const struct tsm_measurement_register *mr;
	int rc;

	ctx = attr->private;
	rc = down_read_interruptible(&ctx->rwsem);
	if (rc)
		return rc;

	mr = &ctx->tm->mrs[attr - ctx->mrs];

	/*
	 * @ctx->in_sync indicates if the MR cache is stale. It is a global
	 * instead of a per-MR flag for simplicity, as most (if not all) archs
	 * allow reading all MRs in oneshot.
	 *
	 * ctx->refresh() is necessary only for LIVE MRs, while others retain
	 * their values from their respective last ctx->write().
	 */
	if ((mr->mr_flags & TSM_MR_F_LIVE) && !ctx->in_sync) {
		up_read(&ctx->rwsem);

		rc = down_write_killable(&ctx->rwsem);
		if (rc)
			return rc;

		if (!ctx->in_sync) {
			rc = ctx->tm->refresh(ctx->tm);
			ctx->in_sync = !rc;
			trace_tsm_mr_refresh(mr, rc);
		}

		downgrade_write(&ctx->rwsem);
	}

	memcpy(buffer, mr->mr_value + off, count);
	trace_tsm_mr_read(mr);

	up_read(&ctx->rwsem);
	return rc ?: count;
}

static ssize_t tm_digest_write(struct file *filp, struct kobject *kobj,
			       const struct bin_attribute *attr, char *buffer,
			       loff_t off, size_t count)
{
	struct tm_context *ctx;
	const struct tsm_measurement_register *mr;
	ssize_t rc;

	/* partial writes are not supported */
	if (off != 0 || count != attr->size)
		return -EINVAL;

	ctx = attr->private;
	mr = &ctx->tm->mrs[attr - ctx->mrs];

	rc = down_write_killable(&ctx->rwsem);
	if (rc)
		return rc;

	rc = ctx->tm->write(ctx->tm, mr, buffer);

	/* mark MR cache stale */
	if (!rc) {
		ctx->in_sync = false;
		trace_tsm_mr_write(mr, buffer);
	}

	up_write(&ctx->rwsem);
	return rc ?: count;
}

/**
 * tsm_mr_create_attribute_group() - creates an attribute group for measurement
 * registers (MRs)
 * @tm: pointer to &struct tsm_measurements containing the MR definitions.
 *

Annotation

Implementation Notes