[PATCH v4 7/8] KVM: arm64: Check whether a VM IOCTL is allowed in pKVM

Fuad Tabba tabba at google.com
Wed Nov 12 02:51:58 PST 2025


Hi Oliver,

On Wed, 12 Nov 2025 at 10:07, Oliver Upton <oupton at kernel.org> wrote:
>
> Hi Fuad,
>
> On Wed, Nov 12, 2025 at 09:20:50AM +0000, Fuad Tabba wrote:
> > +/*
> > + * Check whether the KVM VM IOCTL is allowed in pKVM.
> > + *
> > + * Certain features are allowed only for non-protected VMs in pKVM, which is why
> > + * this takes the VM (kvm) as a parameter.
> > + */
> > +static inline bool kvm_pkvm_ioctl_allowed(struct kvm *kvm, unsigned int ioctl)
> > +{
> > +     switch (ioctl) {
> > +     case KVM_CREATE_IRQCHIP:
> > +             return kvm_pkvm_ext_allowed(kvm, KVM_CAP_IRQCHIP);
> > +     case KVM_ARM_SET_DEVICE_ADDR:
> > +             return kvm_pkvm_ext_allowed(kvm, KVM_CAP_ARM_SET_DEVICE_ADDR);
> > +     case KVM_ARM_MTE_COPY_TAGS:
> > +             return kvm_pkvm_ext_allowed(kvm, KVM_CAP_ARM_MTE);
> > +     case KVM_ARM_SET_COUNTER_OFFSET:
> > +             return kvm_pkvm_ext_allowed(kvm, KVM_CAP_COUNTER_OFFSET);
> > +     case KVM_HAS_DEVICE_ATTR:
> > +     case KVM_SET_DEVICE_ATTR:
> > +     case KVM_GET_DEVICE_ATTR:
> > +             return kvm_pkvm_ext_allowed(kvm, KVM_CAP_DEVICE_CTRL) ||
> > +                    kvm_pkvm_ext_allowed(kvm, KVM_CAP_VM_ATTRIBUTES);
> > +     case KVM_ARM_GET_REG_WRITABLE_MASKS:
> > +             return kvm_pkvm_ext_allowed(kvm, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES);
> > +     default:
> > +             return true;
> > +     }
> > +}
> > +
>
> I was thinking of something a bit more tabular since CCA will impose its
> own restrictions + pKVM could share the ioctl <=> KVM_CAP association.

Sure. Before I respin, how about something along these lines:

struct kvm_ioctl_cap_map {
    unsigned int ioctl;
    long ext;
};

/*
 * Sorted by ioctl to allow for potential binary search,
 * though linear scan is sufficient for this size.
 * (Note to Oliver: If you like, I can add a runtime check if we want
to support binary search.)
 */
static const struct kvm_ioctl_cap_map vm_ioctl_caps[] = {
    { KVM_CREATE_IRQCHIP, KVM_CAP_IRQCHIP },
    { KVM_ARM_SET_DEVICE_ADDR, KVM_CAP_ARM_SET_DEVICE_ADDR },
    { KVM_ARM_MTE_COPY_TAGS, KVM_CAP_ARM_MTE },
    { KVM_SET_DEVICE_ATTR, KVM_CAP_DEVICE_CTRL },
    { KVM_GET_DEVICE_ATTR, KVM_CAP_DEVICE_CTRL },
    { KVM_HAS_DEVICE_ATTR, KVM_CAP_DEVICE_CTRL },
    { KVM_ARM_SET_COUNTER_OFFSET, KVM_CAP_COUNTER_OFFSET },
    { KVM_ARM_GET_REG_WRITABLE_MASKS, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES },
    { KVM_ARM_PREFERRED_TARGET, -1 }, /* Basic IOCTLs, no gating capability */
};

/*
 * Set *ext to the capability, which is -1 for basic capabilities.
 * Return 0 if found, or -EINVAL if no IOCTL matches.
 */
long kvm_get_cap_for_kvm_ioctl(unsigned int ioctl, long *ext)
{
    int i;

    for (i = 0; i < ARRAY_SIZE(vm_ioctl_caps); i++) {
        if (vm_ioctl_caps[i]. ioctl == ioctl)
            *ext = vm_ioctl_caps[i].ext;
            return 0;
   }

    return -EINVAL;
}

> Anyway, ioctl filtering should be an allowlist (default to false) just
> like kvm_pkvm_ext_allowed(). The default assumption is that new UAPI is not
> supported for pVMs unless explicitly stated otherwise.

Of course, that's what we do with capability checks.

Thanks,
/fuad

> Thanks,
> Oliver



More information about the linux-arm-kernel mailing list