Skip to content

kernel/protocols: Introduce OCP support#1138

Draft
n-ramacciotti wants to merge 10 commits into
coconut-svsm:mainfrom
n-ramacciotti:protocols/add_ocp
Draft

kernel/protocols: Introduce OCP support#1138
n-ramacciotti wants to merge 10 commits into
coconut-svsm:mainfrom
n-ramacciotti:protocols/add_ocp

Conversation

@n-ramacciotti

@n-ramacciotti n-ramacciotti commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

RFC PR for observability and configuration protocol.

This is part of my work for Google Summer of code [1] based on the draft protocol posted in the mailing list[2].

For the moment only SVSM_OCP_LIST call is tested. SVSM_OCP_READ and SVSM_OCP_WRITE are here, but yet to be tested.

I'm not sure what should be the name of the 124-byte sources.

Commit messages should be improved. For now, I just wanted to share the current state.

The basic structure for SVSM_OCP_WRITE and SVSM_OCP_READ is here, but for the moment it only returns an error.

To test this, it is possible to use one of these two branches in my linux fork (based on tag v7.1):

These tests print to the log with pr_err. ( For some reason, I couldn't see pr_info, but I don't think that for now is a problem). The tests respectively:

  • Ask for a single entry in the first position
  • Ask for a non exisitng entry
  • Ask for more entries than available
  • Ask for zero entries to return

note: This is not the final linux driver version, but can be useful for testing the svsm side.
note: This require the vm to have a custom guest kernel with the above commits.

In the next few days, I will probably open a PR with the first version to better show the difference in the coconut linux fork. (edit: see coconut-svsm/linux#20)

Tested on a SNP machine. (Thanks @joergroedel )

/cc @stefano-garzarella @kraxel

TODO:

  • For read and write, is required the index. I'm not sure if it is needed to modify the OcpSource to add some function. Another array based on the index of the source can be used to keep track of the correct entry function. I should look more into this.
  • Should this be gated behind a feature?

[1] https://wiki.qemu.org/Google_Summer_of_Code_2026
[2] https://lore.kernel.org/coconut-svsm/aeiLnWdClMC6YuLi@sirius.home.kraxel.org/T/#t

@n-ramacciotti n-ramacciotti force-pushed the protocols/add_ocp branch 2 times, most recently from 7fc1d46 to bb9de70 Compare June 29, 2026 14:55
@tlendacky

Copy link
Copy Markdown
Contributor

Is this meant to be a Coconut specific protocol or a general any SVSM implementation protocol. If the latter, then it needs to be worked out properly and added to the SVSM specification. If the former, then it will need to use one of the reserved reference implementation protocol numbers and needs to be documented for Coconut.

@n-ramacciotti

Copy link
Copy Markdown
Contributor Author

v2:

  • Introduced OcpSourceOperations trait: now each source must be implement it in order to be used in the protocol. It contains read, write and get_source_entry methods. The latter is useful to retrieve the information and interate over the array. read and write have default implementations which return an error.
  • Source name len is now up to 123 bytes. The last one is reserved for null terminator. If one source has a smaller name, the other bytes are padded with 0. It still panics on len discrepancies.
  • Changed ocp_list_request to take into consideration the new trait and get_source_entry_method. Tested with the linux PR.
  • Introduced SVSM_OCP_READ and SVSM_OCP_WRITE. Not yet tested with linux. Their structure is based on the new trait. They are basically a wrapper for the source trait implementation + input checks.
  • Introduce a [test] commit with a fake log buffer to test the list request.
  • For now, the SOURCE array is built at compile time in a static value of trait objects.
  • Each source should implement Sync for safe access.

@n-ramacciotti

n-ramacciotti commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Is this meant to be a Coconut specific protocol or a general any SVSM implementation protocol. If the latter, then it needs to be worked out properly and added to the SVSM specification. If the former, then it will need to use one of the reserved reference implementation protocol numbers and needs to be documented for Coconut.

@tlendacky This is part of my work for google summer of code in the coconut-svsm[1].

This is based on the draft proposal of @joergroedel posted in the mailing list [2].

I believe this will be general for any SVSM implementation protocol.

Sorry for not mentioning this earlier in the PR description. Now it's updated.

[1] https://wiki.qemu.org/Google_Summer_of_Code_2026
[2] https://lore.kernel.org/coconut-svsm/aeiLnWdClMC6YuLi@sirius.home.kraxel.org/T/#t

@00xc 00xc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is in RFC status still, so feel free to discard my comments if the code changes significantly.

Comment thread kernel/src/protocols/ocp.rs
Comment thread kernel/src/protocols/ocp.rs
Comment thread kernel/src/protocols/ocp.rs Outdated
Comment thread kernel/src/protocols/ocp.rs Outdated
@kraxel

kraxel commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

[2] https://lore.kernel.org/coconut-svsm/aeiLnWdClMC6YuLi@sirius.home.kraxel.org/T/#t

The discussion on the protocol died off without conclusion, so I'll use the opportunity to resume it here.

I still think it makes sense to include some information what type of data is returned by a source in the SVSM_OCP_LIST reply (i.e. what became struct OcpSource in this PR). Specifically I think the entries should include enough metadata that the linux kernel driver can proxy the data between svsm and linux userspace without additional knowledge about the sources. Also linux userspace should be able to collect and store metrics without additional knowledge about the source. Only when analyzing the collected data you need to know what the data you got from the svsm actually represents.

The other two ideas from my mail (SVSM_OCP_READ_REGISTER) + (SVSM_OCP_READ_BATCH) can be added to the protocol later on, so lets put those aside for now.

@n-ramacciotti

Copy link
Copy Markdown
Contributor Author

v3:

  • Addressed @00xc's comments:
    • improved panic message and comment when creating OcpSourceFlags
    • Introduced PerCPUMappingGuard and GuestPtr to avoid allocating on the heap. (For now only in SVSM_OCP_LIST handler)

@n-ramacciotti

Copy link
Copy Markdown
Contributor Author

v4:

  • Introduced a new read-only source, which returns the running version of SVSM
  • Introduced a new field kind, which indicates the type of data the source holds
  • Simplified SVSM_OCP_READ and SVSM_OCP_WRITE with removal of heap allocation. Now the copy is source dependent and must be done inside the trait implementation

@n-ramacciotti

n-ramacciotti commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

v5:

  • Introduced max buffer size
  • Introduced testing in linux fork for read operation. It successfully prints coconut version.

Comment thread kernel/src/protocols/ocp.rs Outdated
fn write(&self, _offset: u32, _gpa: PhysAddr, _size: u32) -> Result<u32, SvsmReqError> {
Err(SvsmReqError::unsupported_call())
}
fn get_source_entry(&self) -> &OcpSource;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to allow the trait support multiple sources, so objects implementing the trait are not limited to one?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't we lose direct indexing of the source array in this case?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make things a bit more complicated, yes. You'd need an array with pointer and source index for example. Not fully sure this is a good path forward, maybe it is easier to just create one object per source.

I was wondering if -- for example -- the snp platform object wants allow multiple things being observed such as platform feature flags and cbit position. How would that be done? I see two possible approaches:

  • Implement the Trait for the platform object + allow multiple sources, or
  • Create one object (may or may not be embedded in the platform struct) per source.

The new observability and configuration protocol requires an additional
register `r9` to exchange data between svsm and the guest os.

Add it to the `RequestParams` structure to fulfil this requirement.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Add a new structure, based on OCP protocol specifications.

A source entry has a 4-byte bitfield flag field, where the least
significant bit specifies if a sources is writable or not. The other
bits are reserved.

Additionally, a source entry includes a 120-byte utf-8 encoded name.

Introduce a new const constructor which can be used for initializing
a source. This function will fail if the name is greater than or equal
to 120 bytes, as we want the name to be null terminated. If the name is
less than that value, it will be padded with zeros.

Also include a `kind` field to store information on the source type.
This will help the guest understand which data is transmitted and the
dimension required for the buffer to store these values.

As these sources will be passed to the linux guest, it is useful to
derive `IntoBytes` and `Immutable` for the transfer.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Add a trait that must be implemented by each source in order to be used in
the protocol.

The trait includes a default implementation for the `read` and `write`
methods, as each source may not have that functionality, in which case an
error is returned.

The trait also includes a way to retrieve a reference to the source. This
can be useful for iterating over the list of sources, getting the entry
and assembling the reply to the guest OS.

Require the `Sync` bound as we want to share objects between threads safely.

Introduce the new OCP source array, where each entry should implement the
new trait, making it an array of trait objects.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
The new Observability and Configuration Protocol (OCP) has a protocol
ID value of 5. Add it to the list of known protocols in svsm.

Link it to the correct handler during request processing.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Add the new call identifier (`0`) to the OCP handler and implement
`SVSM_OCP_LIST` following the spec.

If some guest params are incorrect, like buffer alignment or zero entries
requested, an appropriate error will be returned.

The index and the number of entries are 4-bytes, so make sure to use only
the low 32 bits. Since ranges require usize and the constants are usize,
convert these values to usize before using them for simplicity.

Since the guest address is untrusted, handle the check for a valid and non
overlapping region. Additionally, use `PerCPUPageMappingGuard` and
`GuestPtr` to safely map and point that region.

As this call requires SVSM to provide a list of entries, compute the
correct range of entries and extract them from the static `OCP_SOURCES` by
iterating over the array and exploiting the `get_source_entry` method from
the new trait.

Once an entry is available, it is possible to copy it directly to the guest
memory without using temporary heap allocation to store all the entries
together.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Add the new call identifier (`1`) to the OCP handler and implement
`SVSM_OCP_READ` following the spec.

If some guest params are incorrect, like buffer alignment or out of bound
index, an appropriate error will be returned.

The index, the offset and the number of bytes to read are 4-bytes, so make
sure to use only the low 32 bits. Since constants are usize, convert these
values to usize before using them for simplicity.

Since each entry is required to implement the `OcpSourceOperations` trait,
the read method can be exploited to read the bytes from the source.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Add the new call identifier (`2`) to the OCP handler and implement
`SVSM_OCP_WRITE` following the spec.

If some guest params are incorrect, like buffer alignment or out of bound
index, an appropriate error will be returned.

The index, the offset and the number of bytes to write are 4-bytes, so make
sure to use only the low 32 bits. Since constants are usize, convert these
values to usize before using them for simplicity.

Since each entry is required to implement the `OcpSourceOperations` trait,
the write method can be exploited to write the bytes into the source.
Only sources marked with the `writable` flag can be written, otherwise an
error is returned.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
The query protocol is used to check the availability of a protocol at a
given version.

It should take into account every available protocol. Add the new OCP
protocol management.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Introduce a read only source that only returns a static string containing the
current SVSM version.

As the string will always be the same, it can be classified as a static
string.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
Add a source who read and write on an atomic value. Write operations
simply add 1 to the current value.

Signed-off-by: Nicola Ramacciotti <niko.ramak@gmail.com>
@n-ramacciotti

n-ramacciotti commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

v6:

  • moved type field as first element in OcpSource
  • introduced a test source for write operations. Read a counter and increase it multiple times. this will be dropped it's here for testing purposes. (can be tested with the linux PR in coconut fork)
  • rebased on latest main

Todo:

  • improve commit messages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants