linux-coco.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jonathan.cameron@huawei.com>
To: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
Cc: <linux-coco@lists.linux.dev>, <kvmarm@lists.linux.dev>,
	<linux-pci@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<dan.j.williams@intel.com>, <aik@amd.com>, <lukas@wunner.de>,
	Samuel Ortiz <sameo@rivosinc.com>,
	Xu Yilun <yilun.xu@linux.intel.com>,
	Jason Gunthorpe <jgg@ziepe.ca>,
	Suzuki K Poulose <Suzuki.Poulose@arm.com>,
	Steven Price <steven.price@arm.com>,
	Bjorn Helgaas <helgaas@kernel.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Marc Zyngier <maz@kernel.org>, Will Deacon <will@kernel.org>,
	Oliver Upton <oliver.upton@linux.dev>
Subject: Re: [PATCH RESEND v2 06/12] coco: host: arm64: Add RMM device communication helpers
Date: Wed, 29 Oct 2025 18:33:06 +0000	[thread overview]
Message-ID: <20251029183306.0000485c@huawei.com> (raw)
In-Reply-To: <20251027095602.1154418-7-aneesh.kumar@kernel.org>

On Mon, 27 Oct 2025 15:25:56 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:

> - add SMCCC IDs/wrappers for RMI_PDEV_COMMUNICATE/RMI_PDEV_ABORT
> - describe the RMM device-communication ABI (struct rmi_dev_comm_*,
>   cache flags, protocol/object IDs, busy error code)
> - track per-PF0 communication state (buffers, workqueue, cache metadata) and
>   serialize access behind object_lock
> - plumb a DOE/SPDM worker (pdev_communicate_work) plus shared helpers that
>   submit the SMCCC call, cache multi-part responses, and handle retries/abort
> - hook the new helpers into the physical function connect path so IDE
>   setup can drive the device to the expected state
> 
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>

Hi Aneesh,

Comments inline.

> diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/arm-cca-host/rmi-da.c
> index 390b8f05c7cf..592abe0dd252 100644
> --- a/drivers/virt/coco/arm-cca-host/rmi-da.c
> +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c

> +
> +static int doe_send_req_resp(struct pci_tsm *tsm)
> +{
> +	int ret, data_obj_type;
> +	struct cca_host_comm_data *comm_data = to_cca_comm_data(tsm->pdev);
> +	struct rmi_dev_comm_exit *io_exit = &comm_data->io_params->exit;
> +	u8 protocol = io_exit->protocol;
> +
> +	if (protocol == RMI_PROTOCOL_SPDM)
> +		data_obj_type = PCI_DOE_FEATURE_CMA;
> +	else if (protocol == RMI_PROTOCOL_SECURE_SPDM)
> +		data_obj_type = PCI_DOE_FEATURE_SSESSION;
> +	else
> +		return -EINVAL;
> +
> +	/* delay the send */
> +	if (io_exit->req_delay)
> +		fsleep(io_exit->req_delay);
> +
> +	ret = pci_tsm_doe_transfer(tsm->dsm_dev, data_obj_type,
> +				   comm_data->req_buff, io_exit->req_len,
> +				   comm_data->rsp_buff, PAGE_SIZE);
> +	return ret;

	return pci_tsm_doe_transfer()

> +}
> +
> +static inline bool pending_dev_communicate(struct rmi_dev_comm_exit *io_exit)
> +{
> +	bool pending = io_exit->flags & (RMI_DEV_COMM_EXIT_CACHE_REQ |
> +					 RMI_DEV_COMM_EXIT_CACHE_RSP |
> +					 RMI_DEV_COMM_EXIT_SEND |
> +					 RMI_DEV_COMM_EXIT_WAIT |
> +					 RMI_DEV_COMM_EXIT_MULTI);
> +	return pending;
> +}
> +
> +static int ___do_dev_communicate(enum dev_comm_type type, struct pci_tsm *tsm)
> +{
> +	int ret, nbytes, cp_len;
> +	struct cache_object **cache_objp, *cache_obj;
> +	struct cca_host_pf0_dsc *pf0_dsc = to_cca_pf0_dsc(tsm->dsm_dev);
> +	struct cca_host_comm_data *comm_data = to_cca_comm_data(tsm->pdev);
> +	struct rmi_dev_comm_enter *io_enter = &comm_data->io_params->enter;
> +	struct rmi_dev_comm_exit *io_exit = &comm_data->io_params->exit;
> +
> +redo_communicate:
> +
> +	if (type == PDEV_COMMUNICATE)
> +		ret = rmi_pdev_communicate(virt_to_phys(pf0_dsc->rmm_pdev),
> +					   virt_to_phys(comm_data->io_params));
> +	else
> +		ret = RMI_ERROR_INPUT;

Treat this separately for simpler code (assuming you don't have other code that
makes this more complex in later patches).

	if (type != PDEV_COMMUNICATE)
		return -ENXIO;

	ret = rmi_pdev_communicate(virt_to_phys(pf0_dsc->rmm_pdev),
				   virt_to_phys(comm_data->io_params));
	if (ret != RMI...

> +	if (ret != RMI_SUCCESS) {
> +		if (ret == RMI_BUSY)
> +			return -EBUSY;
> +		return -ENXIO;
> +	}
> +
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ ||
> +	    io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_RSP) {
> +
> +		switch (io_exit->cache_obj_id) {
> +		case RMI_DEV_VCA:
> +			cache_objp = &pf0_dsc->vca;
> +			break;
> +		case RMI_DEV_CERTIFICATE:
> +			cache_objp = &pf0_dsc->cert_chain.cache;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		cache_obj = *cache_objp;
> +	}
> +
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ)
> +		cp_len = io_exit->req_cache_len;
> +	else
> +		cp_len = io_exit->rsp_cache_len;
> +
> +	/* response and request len should be <= SZ_4k */
> +	if (cp_len > CACHE_CHUNK_SIZE)
> +		return -EINVAL;
> +
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ ||
> +	    io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_RSP) {
> +		int cache_remaining;
> +		struct cache_object *new_obj;
> +
> +		/* new allocation */
> +		if (!cache_obj) {
> +			cache_obj = kvmalloc(struct_size(cache_obj, buf, CACHE_CHUNK_SIZE),
> +					     GFP_KERNEL);
> +			if (!cache_obj)
> +				return -ENOMEM;
> +
> +			cache_obj->size = CACHE_CHUNK_SIZE;
> +			cache_obj->offset = 0;
> +			*cache_objp = cache_obj;
> +		}
> +
> +		cache_remaining = cache_obj->size - cache_obj->offset;
> +		if (cp_len > cache_remaining) {
> +
> +			if (cache_obj->size + CACHE_CHUNK_SIZE > MAX_CACHE_OBJ_SIZE)
> +				return -EINVAL;
> +
> +			new_obj = kvmalloc(struct_size(cache_obj, buf,
> +						       cache_obj->size + CACHE_CHUNK_SIZE),
> +					   GFP_KERNEL);

Is kvrealloc()? Would avoid need for explicit memcpy / freeing of old object.

> +			if (!new_obj)
> +				return -ENOMEM;
> +			memcpy(new_obj, cache_obj, struct_size(cache_obj, buf, cache_obj->size));
> +			new_obj->size = cache_obj->size + CACHE_CHUNK_SIZE;
> +			*cache_objp = new_obj;
> +			kvfree(cache_obj);
> +		}
> +
> +		/* cache object can change above. */
> +		cache_obj = *cache_objp;
> +	}
> +
> +
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ) {
> +		memcpy(cache_obj->buf + cache_obj->offset,
> +		       (comm_data->req_buff + io_exit->req_cache_offset), io_exit->req_cache_len);
> +		cache_obj->offset += io_exit->req_cache_len;
> +	}
> +
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_RSP) {
> +		memcpy(cache_obj->buf + cache_obj->offset,
> +		       (comm_data->rsp_buff + io_exit->rsp_cache_offset), io_exit->rsp_cache_len);
> +		cache_obj->offset += io_exit->rsp_cache_len;
> +	}
> +
> +	/*
> +	 * wait for last packet request from RMM.
> +	 * We should not find this because our device communication is synchronous
> +	 */
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_WAIT)
> +		return -ENXIO;
> +
> +	/* next packet to send */
> +	if (io_exit->flags & RMI_DEV_COMM_EXIT_SEND) {
> +		nbytes = doe_send_req_resp(tsm);
> +		if (nbytes < 0) {
> +			/* report error back to RMM */
> +			io_enter->status = RMI_DEV_COMM_ERROR;
> +		} else {
> +			/* send response back to RMM */
> +			io_enter->resp_len = nbytes;
> +			io_enter->status = RMI_DEV_COMM_RESPONSE;
> +		}
> +	} else {
> +		/* no data transmitted => no data received */
> +		io_enter->resp_len = 0;
> +		io_enter->status = RMI_DEV_COMM_NONE;
> +	}
> +
> +	if (pending_dev_communicate(io_exit))
> +		goto redo_communicate;
> +
> +	return 0;
> +}
> +
> +static int __do_dev_communicate(enum dev_comm_type type,
> +				struct pci_tsm *tsm, unsigned long error_state)
> +{
> +	int ret;
> +	int state;
> +	struct rmi_dev_comm_enter *io_enter;
> +	struct cca_host_pf0_dsc *pf0_dsc = to_cca_pf0_dsc(tsm->dsm_dev);
> +
> +	io_enter = &pf0_dsc->comm_data.io_params->enter;
> +	io_enter->resp_len = 0;
> +	io_enter->status = RMI_DEV_COMM_NONE;
> +
> +	ret = ___do_dev_communicate(type, tsm);

Think up a more meaningful name.  Counting _ doesn't make for readable code.

> +	if (ret) {
> +		if (type == PDEV_COMMUNICATE)
> +			rmi_pdev_abort(virt_to_phys(pf0_dsc->rmm_pdev));
> +
> +		state = error_state;
> +	} else {
> +		/*
> +		 * Some device communication error will transition the
> +		 * device to error state. Report that.
> +		 */
> +		if (type == PDEV_COMMUNICATE)
> +			ret = rmi_pdev_get_state(virt_to_phys(pf0_dsc->rmm_pdev),
> +						 (enum rmi_pdev_state *)&state);
> +		if (ret)
> +			state = error_state;
Whilst not strictly needed I'd do this as:

		if (type == PDEV_COMMUNICATE) {
			ret = rmi_pdev_get_state(virt_to_phys(pf0_dsc->rmm_pdev),
						 (enum rmi_pdev_state *)&state);
			if (ret)
				state = error_state;
		}

Just to make it clear that reg check is just on the output of the call above.
If we didn't make that call it is definitely zero but nice not to have
to reason about it.


> +	}
> +
> +	if (state == error_state)
> +		pci_err(tsm->pdev, "device communication error\n");
> +
> +	return state;
> +}
> +
> +static int do_dev_communicate(enum dev_comm_type type, struct pci_tsm *tsm,
> +			      unsigned long target_state,
> +			      unsigned long error_state)
> +{
> +	int state;
> +
> +	do {
> +		state = __do_dev_communicate(type, tsm, error_state);
> +
> +		if (state == target_state || state == error_state)
> +			break;

Might as well return rather than break;

> +	} while (1);
> +
> +	return state;
> +}

> +void pdev_communicate_work(struct work_struct *work)
> +{
> +	unsigned long state;
> +	struct pci_tsm *tsm;
> +	struct dev_comm_work *setup_work;
> +	struct cca_host_pf0_dsc *pf0_dsc;
> +
> +	setup_work = container_of(work, struct dev_comm_work, work);
> +	tsm = setup_work->tsm;
> +	pf0_dsc = to_cca_pf0_dsc(tsm->dsm_dev);
Could combine these 3 with declarations for shorter code without much
change to readability.

> +
> +	guard(mutex)(&pf0_dsc->object_lock);
> +	state = do_pdev_communicate(tsm, setup_work->target_state);
> +	WARN_ON(state != setup_work->target_state);
> +
> +	complete(&setup_work->complete);
> +}


> diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/arm-cca-host/rmi-da.h
> index 6764bf8d98ce..1d513e0b74d9 100644
> --- a/drivers/virt/coco/arm-cca-host/rmi-da.h
> +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h

> +struct cca_host_comm_data {
> +	void *rsp_buff;
> +	void *req_buff;
> +	struct rmi_dev_comm_data *io_params;
> +	/*
> +	 * Only one device communication request can be active at

wrap comments to 80 chars. This is around 70ish

> +	 * a time. This limitation comes from using the DOE mailbox
> +	 * at the pdev level. Requests such as get_measurements may
> +	 * span multiple mailbox messages, which must not be
> +	 * interleaved with other SPDM requests.
> +	 */
> +	struct workqueue_struct *work_queue;
> +};
> +
>  /* dsc = device security context */
>  struct cca_host_pf0_dsc {
> +	struct cca_host_comm_data comm_data;
>  	struct pci_tsm_pf0 pci;
>  	struct pci_ide *sel_stream;
>  
>  	void *rmm_pdev;
>  	int num_aux;
>  	void *aux[MAX_PDEV_AUX_GRANULES];
> +
> +	struct mutex object_lock;
> +	struct {
> +		struct cache_object *cache;
> +
> +		void *public_key;
> +		size_t public_key_size;
> +
> +		bool valid;
> +	} cert_chain;
> +	struct cache_object *vca;

There are a enough slightly non obvious things in here like
this vca that I think this structure would benefit from full kernel-doc.

>  };




  reply	other threads:[~2025-10-29 18:33 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-27  9:55 [PATCH RESEND v2 00/12] coc: tsm: Implement ->connect()/->disconnect() callbacks for ARM CCA IDE setup Aneesh Kumar K.V (Arm)
2025-10-27  9:55 ` [PATCH RESEND v2 01/12] KVM: arm64: RMI: Export kvm_has_da_feature Aneesh Kumar K.V (Arm)
2025-10-29 16:39   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 02/12] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers Aneesh Kumar K.V (Arm)
2025-10-29 16:52   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 03/12] coco: guest: arm64: Drop dummy RSI platform device stub Aneesh Kumar K.V (Arm)
2025-10-29 16:54   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 04/12] coco: host: arm64: Add host TSM callback and IDE stream allocation support Aneesh Kumar K.V (Arm)
2025-10-29 17:18   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 05/12] coco: host: arm64: Build and register RMM pdev descriptors Aneesh Kumar K.V (Arm)
2025-10-29 17:37   ` Jonathan Cameron
2025-10-30  8:44     ` Aneesh Kumar K.V
2025-10-30 10:00       ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 06/12] coco: host: arm64: Add RMM device communication helpers Aneesh Kumar K.V (Arm)
2025-10-29 18:33   ` Jonathan Cameron [this message]
2025-10-30  9:18     ` Aneesh Kumar K.V
2025-10-30 10:00       ` Jonathan Cameron
2025-10-30 14:04     ` Aneesh Kumar K.V
2025-10-30 18:02       ` Jonathan Cameron
2025-10-30 16:20     ` Aneesh Kumar K.V
2025-10-30 18:12       ` Jonathan Cameron
2025-10-31  8:04         ` Aneesh Kumar K.V
2025-10-31 12:07           ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 07/12] coco: host: arm64: Add helper to stop and tear down an RMM pdev Aneesh Kumar K.V (Arm)
2025-10-29 18:34   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 08/12] coco: host: arm64: Instantiate RMM pdev during device connect Aneesh Kumar K.V (Arm)
2025-10-29 18:38   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 09/12] X.509: Make certificate parser public Aneesh Kumar K.V (Arm)
2025-10-27  9:56 ` [PATCH RESEND v2 10/12] X.509: Parse Subject Alternative Name in certificates Aneesh Kumar K.V (Arm)
2025-10-27  9:56 ` [PATCH RESEND v2 11/12] X.509: Move certificate length retrieval into new helper Aneesh Kumar K.V (Arm)
2025-10-27  9:56 ` [PATCH RESEND v2 12/12] coco: host: arm64: Register device public key with RMM Aneesh Kumar K.V (Arm)
2025-10-29 17:19   ` Jason Gunthorpe
2025-10-29 18:53   ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251029183306.0000485c@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=Suzuki.Poulose@arm.com \
    --cc=aik@amd.com \
    --cc=aneesh.kumar@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=dan.j.williams@intel.com \
    --cc=helgaas@kernel.org \
    --cc=jgg@ziepe.ca \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=sameo@rivosinc.com \
    --cc=steven.price@arm.com \
    --cc=will@kernel.org \
    --cc=yilun.xu@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).