Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions arch/x86/include/asm/acrn.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
*/
#define ACRN_CPUID_TIMING_INFO 0x40000010

/* Select x86 specific features in <linux/acrn.h> */
#define __ACRN_HAVE_RESET_VM_V2
#define __ACRN_HAVE_SET_REG

void acrn_setup_intr_handler(void (*handler)(void));
void acrn_remove_intr_handler(void);

Expand Down
63 changes: 62 additions & 1 deletion drivers/virt/acrn/hsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ static int pmcmd_ioctl(u64 cmd, void __user *uptr)
return ret;
}

static bool cmd_without_vm(unsigned int cmd)
{
const unsigned int cmds[] = {
ACRN_IOCTL_CREATE_VM,
ACRN_IOCTL_GET_CAPS
};
int i;

for (i = 0; i < ARRAY_SIZE(cmds); i++) {
if (cmd == cmds[i])
return true;
}

return false;
}

/*
* HSM relies on hypercall layer of the ACRN hypervisor to do the
* sanity check against the input parameters.
Expand All @@ -109,13 +125,16 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
unsigned long ioctl_param)
{
struct acrn_vm *vm = filp->private_data;
struct acrn_vm_reset_state *vm_reset;
struct acrn_cap_bitmap *cap_bitmap;
struct acrn_vm_creation *vm_param;
struct acrn_vcpu_regs *cpu_regs;
struct acrn_ioreq_notify notify;
struct acrn_ptdev_irq *irq_info;
struct acrn_ioeventfd ioeventfd;
struct acrn_vm_memmap memmap;
struct acrn_mmiodev *mmiodev;
struct acrn_one_reg *one_reg;
struct acrn_msi_entry *msi;
struct acrn_pcidev *pcidev;
struct acrn_irqfd irqfd;
Expand All @@ -124,7 +143,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
u64 cstate_cmd;
int i, ret = 0;

if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) {
if (vm->vmid == ACRN_INVALID_VMID && !cmd_without_vm(cmd)) {
dev_dbg(acrn_dev.this_device,
"ioctl 0x%x: Invalid VM state!\n", cmd);
return -EINVAL;
Expand Down Expand Up @@ -222,6 +241,48 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
vm->vmid);
kfree(cpu_regs);
break;
case ACRN_IOCTL_GET_CAPS:
cap_bitmap = memdup_user((void __user *)ioctl_param,
sizeof(struct acrn_cap_bitmap));
if (IS_ERR(cap_bitmap))
return PTR_ERR(cap_bitmap);

ret = hcall_get_caps(virt_to_phys(cap_bitmap));
if (ret == 0)
ret = copy_to_user((void __user *)ioctl_param,
cap_bitmap,
sizeof(struct acrn_cap_bitmap));

if (ret < 0)
dev_dbg(acrn_dev.this_device, "Failed to get CAP\n");

kfree(cap_bitmap);
break;
case ACRN_IOCTL_RESET_VM_V2:
vm_reset = memdup_user((void __user *)ioctl_param,
sizeof(struct acrn_vm_reset_state));
if (IS_ERR(vm_reset))
return PTR_ERR(vm_reset);

ret = hcall_reset_vm_v2(vm->vmid, virt_to_phys(vm_reset));
if (ret < 0)
dev_dbg(acrn_dev.this_device,
"Failed to restart VM %u!\n", vm->vmid);
kfree(vm_reset);
break;
case ACRN_IOCTL_SET_ONE_REG:
one_reg = memdup_user((void __user *)ioctl_param,
sizeof(struct acrn_one_reg));
if (IS_ERR(one_reg))
return PTR_ERR(one_reg);

ret = hcall_set_one_reg(vm->vmid, virt_to_phys(one_reg));
if (ret < 0)
dev_dbg(acrn_dev.this_device,
"Failed to set one reg from VM%u/VCPU%u!\n",
vm->vmid, one_reg->vcpu_id);
kfree(one_reg);
break;
case ACRN_IOCTL_SET_MEMSEG:
if (copy_from_user(&memmap, (void __user *)ioctl_param,
sizeof(memmap)))
Expand Down
42 changes: 42 additions & 0 deletions drivers/virt/acrn/hypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#define HC_ID_GEN_BASE 0x0UL
#define HC_SOS_REMOVE_CPU _HC_ID(HC_ID, HC_ID_GEN_BASE + 0x01)
#define HC_GET_CAPS _HC_ID(HC_ID, HC_ID_GEN_BASE + 0x03)

#define HC_ID_VM_BASE 0x10UL
#define HC_CREATE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x00)
Expand All @@ -23,6 +24,12 @@
#define HC_PAUSE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x03)
#define HC_RESET_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x05)
#define HC_SET_VCPU_REGS _HC_ID(HC_ID, HC_ID_VM_BASE + 0x06)
#ifdef __ACRN_HAVE_RESET_VM_V2
#define HC_RESET_VM_V2 _HC_ID(HC_ID, HC_ID_VM_BASE + 0x07)
#endif
#ifdef __ACRN_HAVE_SET_REG
#define HC_SET_ONE_REG _HC_ID(HC_ID, HC_ID_VM_BASE + 0x08)
#endif

#define HC_ID_IRQ_BASE 0x20UL
#define HC_INJECT_MSI _HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x03)
Expand Down Expand Up @@ -121,6 +128,41 @@ static inline long hcall_reset_vm(u64 vmid)
return acrn_hypercall1(HC_RESET_VM, vmid);
}

/**
* hcall_reset_vm_v2() - Reset a User VM
* @vmid: User VM ID
* @addr: Service VM GPA of the reset info
*
* Return: 0 on success, <0 on failure
*/
static inline long hcall_reset_vm_v2(u64 vmid, u64 addr)
{
return acrn_hypercall2(HC_RESET_VM_V2, vmid, addr);
}

/**
* hcall_get_caps() - Get supported capabilities
* @addr: Service VM GPA of the capability bitmap info
*
* Return: 0 on success, <0 on failure
*/
static inline long hcall_get_caps(u64 addr)
{
return acrn_hypercall1(HC_GET_CAPS, addr);
}

/**
* hcall_set_one_reg() - Set one register of a VCPU from User VM
* @vmid: User VM ID
* @addr: Service VM GPA of the one register info
*
* Return: 0 on success, <0 on failure
*/
static inline long hcall_set_one_reg(u64 vmid, u64 addr)
{
return acrn_hypercall2(HC_SET_ONE_REG, vmid, addr);
}

/**
* hcall_set_vcpu_regs() - Set up registers of virtual CPU of a User VM
* @vmid: User VM ID
Expand Down
52 changes: 52 additions & 0 deletions include/uapi/linux/acrn.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#ifndef _UAPI_ACRN_H
#define _UAPI_ACRN_H

#include <asm/acrn.h>
#include <linux/types.h>
#include <linux/uuid.h>

Expand Down Expand Up @@ -418,6 +419,39 @@ struct acrn_pcidev {
__u32 bar[ACRN_PCI_NUM_BARS];
};

struct acrn_vm_reset_state {
__u32 vm_reset_mode;
__u32 reserved[7];
};

struct acrn_cap_bitmap {
__u32 index;
__u64 bitmap;
};

struct segment_sel {
__u16 selector;
__u64 base;
__u32 limit;
__u32 attr;
};

union acrn_reg {
__u16 wval;
__u32 dval;
__u64 qval;
/** for GDTR and IDTR */
struct acrn_descriptor_ptr dpt;
struct segment_sel seg_sel;
};

struct acrn_one_reg {
/** virtual CPU ID for the VCPU */
__u16 vcpu_id;
__u32 reg;
union acrn_reg value;
};

/**
* struct acrn_mmiodev - Info for assigning or de-assigning a MMIO device
* @name: Name of the MMIO device.
Expand Down Expand Up @@ -665,6 +699,16 @@ struct sbuf_setup_param {
/* The ioctl type, documented in ioctl-number.rst */
#define ACRN_IOCTL_TYPE 0xA2

/*
* Extension capability list.
*/
#ifdef __ACRN_HAVE_RESET_VM_V2
#define ACRN_CAP_RESET_VM_V2 0
#endif
#ifdef __ACRN_HAVE_SET_REG
#define ACRN_CAP_SET_REG 1
#endif

/*
* Common IOCTL IDs definition for ACRN userspace
*/
Expand All @@ -680,6 +724,14 @@ struct sbuf_setup_param {
_IO(ACRN_IOCTL_TYPE, 0x15)
#define ACRN_IOCTL_SET_VCPU_REGS \
_IOW(ACRN_IOCTL_TYPE, 0x16, struct acrn_vcpu_regs)
#define ACRN_IOCTL_GET_CAPS \
_IOWR(ACRN_IOCTL_TYPE, 0x17, __u64)
/* Available with ACRN_CAP_RESET_VM_V2 */
#define ACRN_IOCTL_RESET_VM_V2 \
_IOW(ACRN_IOCTL_TYPE, 0x18, struct acrn_vm_reset_state)
/* Available with ACRN_CAP_SET_REG */
#define ACRN_IOCTL_SET_ONE_REG \
_IOW(ACRN_IOCTL_TYPE, 0x19, struct acrn_one_reg)

#define ACRN_IOCTL_INJECT_MSI \
_IOW(ACRN_IOCTL_TYPE, 0x23, struct acrn_msi_entry)
Expand Down