hv: hypercall: add support to change guest page write permission

Add hcall_change_vm_page_wp_perm to change guest one page write permission.

Signed-off-by: Li, Fei1 <fei1.li@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Li, Fei1 2018-07-24 10:51:54 +08:00 committed by lijinxia
parent efd5ac4814
commit 34c6862a28
4 changed files with 91 additions and 0 deletions

View File

@ -116,6 +116,11 @@ int vmcall_vmexit_handler(struct vcpu *vcpu)
ret = hcall_set_vm_memory_regions(vm, param1);
break;
case HC_VM_WRITE_PROTECT_PAGE:
ret = hcall_write_protect_page(vm, (uint16_t)param1, param2);
break;
case HC_VM_PCI_MSIX_REMAP:
/* param1: vmid */
ret = hcall_remap_pci_msix(vm, (uint16_t)param1, param2);

View File

@ -558,6 +558,60 @@ int32_t hcall_set_vm_memory_regions(struct vm *vm, uint64_t param)
return 0;
}
static int32_t write_protect_page(struct vm *vm, struct wp_data *wp)
{
uint64_t hpa, base_paddr;
uint64_t prot_set;
uint64_t prot_clr;
hpa = gpa2hpa(vm, wp->gpa);
dev_dbg(ACRN_DBG_HYCALL, "[vm%d] gpa=0x%x hpa=0x%x",
vm->attr.id, wp->gpa, hpa);
base_paddr = get_hv_image_base();
if (((hpa <= base_paddr) && (hpa + CPU_PAGE_SIZE > base_paddr)) ||
((hpa >= base_paddr) &&
(hpa < base_paddr + CONFIG_RAM_SIZE))) {
pr_err("%s: overlap the HV memory region.", __func__);
return -EINVAL;
}
prot_set = (wp->set != 0U) ? 0UL : EPT_WR;
prot_clr = (wp->set != 0U) ? EPT_WR : 0UL;
return ept_mr_modify(vm, (uint64_t *)vm->arch_vm.nworld_eptp,
wp->gpa, CPU_PAGE_SIZE, prot_set, prot_clr);
}
int32_t hcall_write_protect_page(struct vm *vm, uint16_t vmid, uint64_t wp_gpa)
{
struct wp_data wp;
struct vm *target_vm = get_vm_from_vmid(vmid);
if ((vm == NULL) || (target_vm == NULL)) {
return -EINVAL;
}
if (!is_vm0(vm)) {
pr_err("%s: Not coming from service vm", __func__);
return -EPERM;
}
if (is_vm0(target_vm)) {
pr_err("%s: Targeting to service vm", __func__);
return -EINVAL;
}
(void)memset((void *)&wp, 0U, sizeof(wp));
if (copy_from_gpa(vm, &wp, wp_gpa, sizeof(wp)) != 0) {
pr_err("%s: Unable copy param to vm\n", __func__);
return -EFAULT;
}
return write_protect_page(target_vm, &wp);
}
int32_t hcall_remap_pci_msix(struct vm *vm, uint16_t vmid, uint64_t param)
{
int32_t ret = 0;

View File

@ -228,6 +228,18 @@ int32_t hcall_set_vm_memory_region(struct vm *vm, uint16_t vmid, uint64_t param)
*/
int32_t hcall_set_vm_memory_regions(struct vm *vm, uint64_t param);
/**
* @brief change guest memory page write permission
*
* @param vm Pointer to VM data structure
* @param vmid ID of the VM
* @param param guest physical address. This gpa points to
* struct wp_data
*
* @return 0 on success, non-zero on error.
*/
int32_t hcall_write_protect_page(struct vm *vm, uint16_t vmid, uint64_t param);
/**
* @brief remap PCI MSI interrupt
*

View File

@ -53,6 +53,7 @@
#define HC_VM_SET_MEMORY_REGION _HC_ID(HC_ID, HC_ID_MEM_BASE + 0x00UL)
#define HC_VM_GPA2HPA _HC_ID(HC_ID, HC_ID_MEM_BASE + 0x01UL)
#define HC_VM_SET_MEMORY_REGIONS _HC_ID(HC_ID, HC_ID_MEM_BASE + 0x02UL)
#define HC_VM_WRITE_PROTECT_PAGE _HC_ID(HC_ID, HC_ID_MEM_BASE + 0x03UL)
/* PCI assignment*/
#define HC_ID_PCI_BASE 0x50UL
@ -109,6 +110,7 @@
struct vm_memory_region {
#define MR_ADD 0U
#define MR_DEL 2U
#define MR_MODIFY 3U
/** set memory region type: MR_ADD or MAP_DEL */
uint32_t type;
@ -148,6 +150,24 @@ struct set_regions {
uint64_t regions_gpa;
} __attribute__((aligned(8)));
/**
* @brief Info to change guest one page write protect permission
*
* the parameter for HC_VM_WRITE_PROTECT_PAGE hypercall
*/
struct wp_data {
/** set page write protect permission.
* ture: set the wp; flase: clear the wp
*/
uint8_t set;
/** Reserved */
uint64_t pad:56;
/** the guest physical address of the page to change */
uint64_t gpa;
} __aligned(8);
/**
* Setup parameter for share buffer, used for HC_SETUP_SBUF hypercall
*/