On Fri, Oct 08, 2021 at 01:04:30PM -0500, Brijesh Singh wrote:Noted.
+static int vmgexit_psc(struct snp_psc_desc *desc)
+{
+ int cur_entry, end_entry, ret;
+ struct snp_psc_desc *data;
+ struct ghcb_state state;
+ struct ghcb *ghcb;
+ struct psc_hdr *hdr;
+ unsigned long flags;
int cur_entry, end_entry, ret;
struct snp_psc_desc *data;
struct ghcb_state state;
struct psc_hdr *hdr;
unsigned long flags;
struct ghcb *ghcb;
that's properly sorted.
+
+ local_irq_save(flags);
What is that protecting against? Comment about it?
Aha, __sev_get_ghcb() needs to run with IRQs disabled because it is
using the per-CPU GHCB.
+
+ ghcb = __sev_get_ghcb(&state);
+ if (unlikely(!ghcb))
+ panic("SEV-SNP: Failed to get GHCB\n");
+
+ /* Copy the input desc into GHCB shared buffer */
+ data = (struct snp_psc_desc *)ghcb->shared_buffer;
+ memcpy(ghcb->shared_buffer, desc, sizeof(*desc));
That shared buffer has a size - check it vs the size of the desc thing.
+ if (WARN(ret || ghcb->save.sw_exit_info_2,
+ "SEV-SNP: PSC failed ret=%d exit_info_2=%llx\n",
+ ret, ghcb->save.sw_exit_info_2)) {
+ ret = 1;
That ret = 1 goes unused with that "return 0" at the end. It should be
"return ret" at the end.. Ditto for the others. Audit all your exit
paths in this function.
+
+ /* Verify that reserved bit is not set */
+ if (WARN(hdr->reserved, "Reserved bit is set in the PSC header\n")) {
Shouldn't that thing happen first after the HV call?
+
+ /*
+ * The GHCB specification provides the flexibility to
+ * use either 4K or 2MB page size in the RMP table.
+ * The current SNP support does not keep track of the
+ * page size used in the RMP table. To avoid the
+ * overlap request,
"avoid overlap request"?
No clue what that means. In general, that comment is talking about
something in the future and is more confusing than explaining stuff.
use the 4K page size in the RMP
+ * table.
+ */
+ e->pagesize = RMP_PG_SIZE_4K;
+
+ vaddr = vaddr + PAGE_SIZE;
+ e++;
+ i++;
+ }
+
+ if (vmgexit_psc(data))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
+}
+
+static void set_page_state(unsigned long vaddr, unsigned int npages, int op)
Yeah, so this should be named
set_pages_state - notice the plural "pages"
because it works on multiple pages, @npages exactly.
Noted.+{
+ unsigned long vaddr_end, next_vaddr;
+ struct snp_psc_desc *desc;
+
+ vaddr = vaddr & PAGE_MASK;
+ vaddr_end = vaddr + (npages << PAGE_SHIFT);
Take those two...
+
+ desc = kmalloc(sizeof(*desc), GFP_KERNEL_ACCOUNT);
+ if (!desc)
+ panic("SEV-SNP: failed to allocate memory for PSC descriptor\n");
... and put them here.