From: Yi Zhang <yi.z.zhang@linux.intel.com>
To: Christoph Hellwig <hch@infradead.org>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
pbonzini@redhat.com, rkrcmar@redhat.com
Subject: Re: [PATCH RFC 00/10] Intel EPT-Based Sub-page Write Protection Support.
Date: Wed, 18 Oct 2017 22:02:48 +0800 [thread overview]
Message-ID: <20171018140247.GA28204@dazhang1-ssd.sh.intel.com> (raw)
In-Reply-To: <20171018070936.GA10808@infradead.org>
[-- Attachment #1: Type: text/plain, Size: 962 bytes --]
On 2017-10-18 at 00:09:36 -0700, Christoph Hellwig wrote:
> > We introduced 2 ioctls to let user application to set/get subpage write protection bitmap per gfn, each gfn corresponds to a bitmap.
> > The user application, qemu, or some other security control daemon. will set the protection bitmap via this ioctl.
> > the API defined as:
> > struct kvm_subpage {
> > __u64 base_gfn;
> > __u64 npages;
> > /* sub-page write-access bitmap array */
> > __u32 access_map[SUBPAGE_MAX_BITMAP];
> > }sp;
> > kvm_vm_ioctl(s, KVM_SUBPAGES_SET_ACCESS, &sp)
> > kvm_vm_ioctl(s, KVM_SUBPAGES_GET_ACCESS, &sp)
>
> What is the use case for this feature?
Thanks for your review Chirs,
I have prepared a draft version of tools which embedded in the qemu
command line, mean that we could set/get the subpage protection via qemu
command.
Attached the qemu patch, it is a pre-design version, I'm considering to
change the interface to hypercall as Paolo's advice.
[-- Attachment #2: 0001-x86-Intel-Sub-Page-Protection-support.patch --]
[-- Type: text/x-diff, Size: 10314 bytes --]
>From a369bed5d986dccb3ca36dc5a27c6220ca2d1405 Mon Sep 17 00:00:00 2001
From: Zhang Yi Z <yi.z.zhang@linux.intel.com>
Date: Tue, 14 Mar 2017 15:11:38 +0800
Subject: [PATCH] x86: Intel Sub-Page Protection support
Signed-off-by: He Chen <he.chen@linux.intel.com>
Signed-off-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
---
hmp-commands.hx | 26 ++++++++++++++++++++++++++
hmp.c | 26 ++++++++++++++++++++++++++
hmp.h | 2 ++
include/sysemu/kvm.h | 2 ++
kvm-all.c | 40 ++++++++++++++++++++++++++++++++++++++++
| 15 +++++++++++++++
qapi-schema.json | 41 +++++++++++++++++++++++++++++++++++++++++
qmp.c | 43 +++++++++++++++++++++++++++++++++++++++++++
target/i386/kvm.c | 22 ++++++++++++++++++++++
9 files changed, 217 insertions(+)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8819281..7a57411 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1766,6 +1766,32 @@ Set QOM property @var{property} of object at location @var{path} to value @var{v
ETEXI
{
+ .name = "get-subpage",
+ .args_type = "base_gfn:l,npages:l,filename:str",
+ .params = "base_gfn npages filename",
+ .help = "get the write-protect bitmap setting of sub-page protectio",
+ .cmd = hmp_get_subpage,
+ },
+
+STEXI
+@item get-subpage @var{base_gfn} @var{npages} @var{file}
+Get the write-protect bitmap setting of sub-page protection in the range of @var{base_gfn} to @var{base_gfn} + @var{npages}
+ETEXI
+
+ {
+ .name = "set-subpage",
+ .args_type = "base_gfn:l,npages:l,wp_map:i",
+ .params = "base_gfn npages",
+ .help = "set the write-protect bitmap setting of sub-page protectio",
+ .cmd = hmp_set_subpage,
+ },
+
+STEXI
+@item set-subpage @var{base_gfn} @var{npages}
+Get the write-protect bitmap setting of sub-page protection in the range of @var{base_gfn} to @var{base_gfn} + @var{npages}
+ETEXI
+
+ {
.name = "info",
.args_type = "item:s?",
.params = "[subcommand]",
diff --git a/hmp.c b/hmp.c
index 261843f..7d217e9 100644
--- a/hmp.c
+++ b/hmp.c
@@ -2614,3 +2614,29 @@ void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict)
}
qapi_free_GuidInfo(info);
}
+
+void hmp_get_subpage(Monitor *mon, const QDict *qdict)
+{
+ uint64_t base_gfn = qdict_get_int(qdict, "base_gfn");
+ uint64_t npages = qdict_get_int(qdict, "npages");
+ const char *filename = qdict_get_str(qdict, "filename");
+ Error *err = NULL;
+
+ monitor_printf(mon, "base_gfn: %ld, npages: %ld, file: %s\n", base_gfn, npages, filename);
+
+ qmp_get_subpage(base_gfn, npages, filename, &err);
+ hmp_handle_error(mon, &err);
+}
+
+void hmp_set_subpage(Monitor *mon, const QDict *qdict)
+{
+ uint64_t base_gfn = qdict_get_int(qdict, "base_gfn");
+ uint64_t npages = qdict_get_int(qdict, "npages");
+ uint32_t wp_map = qdict_get_int(qdict, "wp_map");
+ Error *err = NULL;
+
+ monitor_printf(mon, "base_gfn: %ld, npages: %ld, wp_map: %d\n", base_gfn, npages, wp_map);
+
+ qmp_set_subpage(base_gfn, npages, wp_map, &err);
+ hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 799fd37..b72143f 100644
--- a/hmp.h
+++ b/hmp.h
@@ -138,5 +138,7 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict);
void hmp_info_dump(Monitor *mon, const QDict *qdict);
void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict);
void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict);
+void hmp_get_subpage(Monitor *mon, const QDict *qdict);
+void hmp_set_subpage(Monitor *mon, const QDict *qdict);
#endif
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 24281fc..f7c1340 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -528,4 +528,6 @@ int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source);
*/
int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target);
int kvm_get_max_memslots(void);
+int kvm_get_subpage_wp_map(uint64_t base_gfn, uint32_t *buf, uint64_t len);
+int kvm_set_subpage_wp_map(uint64_t base_gfn, uint64_t npages, uint32_t wp_map);
#endif
diff --git a/kvm-all.c b/kvm-all.c
index 9040bd5..58cc0a4 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -2593,6 +2593,46 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
return r;
}
+int kvm_get_subpage_wp_map(uint64_t base_gfn, uint32_t *buf,
+ uint64_t len)
+{
+ KVMState *s = kvm_state;
+ struct kvm_subpage sp = {};
+ int n;
+
+ sp.base_gfn = base_gfn;
+ sp.npages = len;
+
+
+ if (kvm_vm_ioctl(s, KVM_SUBPAGES_GET_ACCESS, &sp) < 0) {
+ DPRINTF("ioctl failed %d\n", errno);
+ return -1;
+ }
+
+ memcpy(buf, sp.access_map, n * sizeof(uint32_t));
+
+ return n;
+}
+
+int kvm_set_subpage_wp_map(uint64_t base_gfn, uint64_t npages,
+ uint32_t wp_map)
+{
+ KVMState *s = kvm_state;
+ struct kvm_subpage sp = {};
+
+ sp.base_gfn = base_gfn;
+ sp.npages = npages;
+ sp.access_map[0] = wp_map;
+
+
+ if (kvm_vm_ioctl(s, KVM_SUBPAGES_SET_ACCESS, &sp) < 0) {
+ DPRINTF("ioctl failed %d\n", errno);
+ return -1;
+ }
+
+ return 0;
+}
+
static void kvm_accel_class_init(ObjectClass *oc, void *data)
{
AccelClass *ac = ACCEL_CLASS(oc);
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 4e082a8..69de005 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -205,6 +205,7 @@ struct kvm_hyperv_exit {
#define KVM_EXIT_S390_STSI 25
#define KVM_EXIT_IOAPIC_EOI 26
#define KVM_EXIT_HYPERV 27
+#define KVM_EXIT_SPP 28
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -360,6 +361,10 @@ struct kvm_run {
struct {
__u8 vector;
} eoi;
+ /* KVM_EXIT_SPP */
+ struct {
+ __u64 addr;
+ } spp;
/* KVM_EXIT_HYPERV */
struct kvm_hyperv_exit hyperv;
/* Fix the size of the union. */
@@ -1126,6 +1131,8 @@ enum kvm_device_type {
struct kvm_userspace_memory_region)
#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
+#define KVM_SUBPAGES_GET_ACCESS _IOR(KVMIO, 0x49, __u64)
+#define KVM_SUBPAGES_SET_ACCESS _IOW(KVMIO, 0x4a, __u64)
/* enable ucontrol for s390 */
struct kvm_s390_ucas_mapping {
@@ -1354,4 +1361,12 @@ struct kvm_assigned_msix_entry {
#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
+/* for KVM_SUBPAGES_GET_ACCESS and KVM_SUBPAGES_SET_ACCESS */
+#define SUBPAGE_MAX_BITMAP 256
+struct kvm_subpage {
+ __u64 base_gfn;
+ __u64 npages;
+ __u32 access_map[SUBPAGE_MAX_BITMAP]; /* sub-page write-access bitmap array */
+};
+
#endif /* __LINUX_KVM_H */
diff --git a/qapi-schema.json b/qapi-schema.json
index 32b4a4b..d6b46bb 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -6267,3 +6267,44 @@
# Since 2.9
##
{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
+
+##
+# @get-subpage:
+#
+# This command will get setting information of sub-page
+# protection.
+#
+# Since: 2.10
+#
+# Example:
+#
+# -> { "execute": "get-subpage",
+# "arguments": { "base_gfn": 0x1000,
+# "npages": 10,
+# "filename": "/tmp/spp_info" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'get-subpage',
+ 'data': {'base_gfn': 'uint64', 'npages': 'uint64', 'filename': 'str'} }
+
+
+##
+# @set-subpage:
+#
+# This command will set sub-page protection for given GFNs.
+#
+# Since: 2.10
+#
+# Example:
+#
+# -> { "execute": "set-subpage",
+# "arguments": { "base_gfn": 0x1000,
+# "npages": 10,
+# "wp_map": 0xffff0000 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'set-subpage',
+ 'data': {'base_gfn': 'uint64', 'npages': 'uint64', 'wp_map': 'uint32'} }
+
diff --git a/qmp.c b/qmp.c
index fa82b59..274efdb 100644
--- a/qmp.c
+++ b/qmp.c
@@ -717,3 +717,46 @@ ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
return head;
}
+
+#define SUBPAGE_BUF_LEN 256
+void qmp_get_subpage(uint64_t base_gfn, uint64_t npages,
+ const char *filename, Error **errp)
+{
+ FILE *f;
+ uint64_t n;
+ uint32_t buf[SUBPAGE_BUF_LEN];
+
+ f = fopen(filename, "wb");
+ if (!f) {
+ error_setg_file_open(errp, errno, filename);
+ return;
+ }
+
+ while (npages != 0) {
+ n = npages;
+ if (n > SUBPAGE_BUF_LEN)
+ n = SUBPAGE_BUF_LEN;
+ if (kvm_get_subpage_wp_map(base_gfn, buf, n) < 0) {
+ error_setg(errp, QERR_IO_ERROR);
+ goto exit;
+ }
+ if (fwrite(buf, 4, n, f) != n) {
+ error_setg(errp, QERR_IO_ERROR);
+ goto exit;
+ }
+ base_gfn += n;
+ npages -= n;
+ }
+
+exit:
+ fclose(f);
+}
+
+void qmp_set_subpage(uint64_t base_gfn, uint64_t npages,
+ uint32_t wp_map, Error **errp)
+{
+ if (kvm_set_subpage_wp_map(base_gfn, npages, wp_map) < 0)
+ error_setg(errp, QERR_IO_ERROR);
+
+}
+
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 472399f..18a43d7 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -3147,6 +3147,23 @@ static int kvm_handle_debug(X86CPU *cpu,
return ret;
}
+static int kvm_handle_spp(uint64_t addr)
+{
+ /*
+ uint64_t base_gfn = addr >> 12;
+ uint64_t offset = addr & ((1 << 12) - 1);
+ int subpage_index = offset >> 7;
+ uint32_t mask;
+
+ kvm_get_subpage_wp_map(base_gfn, &mask, 1);
+ mask |= 1UL << subpage_index;
+ return kvm_set_subpage_wp_map(base_gfn, 1, mask);
+ */
+
+ fprintf(stderr, "QEMU-SPP: we are in kvm_handle_spp now, addr=0x%lx!\n", addr);
+ return 0;
+}
+
void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
{
const uint8_t type_code[] = {
@@ -3240,6 +3257,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
ioapic_eoi_broadcast(run->eoi.vector);
ret = 0;
break;
+ case KVM_EXIT_SPP:
+ DPRINTF("handle_spp\n");
+ kvm_handle_spp(run->spp.addr);
+ ret = 0;
+ break;
default:
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
ret = -1;
--
2.7.4
next prev parent reply other threads:[~2017-10-18 14:02 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-13 23:11 Zhang Yi
2017-10-13 16:57 ` Jim Mattson
2017-10-13 21:13 ` Paolo Bonzini
2017-10-16 0:08 ` Yi Zhang
2017-10-18 9:35 ` Paolo Bonzini
2017-10-18 14:07 ` Yi Zhang
2017-10-19 11:57 ` Paolo Bonzini
2017-10-20 8:51 ` Yi Zhang
2017-10-18 14:13 ` Mihai Donțu
2017-10-20 8:47 ` Yi Zhang
2017-10-20 17:06 ` Mihai Donțu
2017-10-24 7:52 ` Yi Zhang
2017-10-16 0:01 ` Yi Zhang
2017-10-13 23:12 ` [PATCH RFC 01/10] KVM: VMX: Added EPT Subpage Protection Documentation Zhang Yi
2017-10-13 23:12 ` [PATCH RFC 02/10] x86/cpufeature: Add intel Sub-Page Protection to CPU features Zhang Yi
2017-10-13 23:13 ` [PATCH RFC 03/10] KVM: VMX: Added VMX SPP feature flags and VM-Execution Controls Zhang Yi
2017-10-13 23:13 ` [PATCH RFC 04/10] KVM: VMX: Introduce the SPPTP and SPP page table Zhang Yi
2017-10-13 23:14 ` [PATCH RFC 05/10] KVM: VMX: Introduce SPP-Induced vm exit and it's handle Zhang Yi
2017-10-13 23:14 ` [PATCH RFC 06/10] KVM: VMX: Added handle of SPP write protection fault Zhang Yi
2017-10-13 23:14 ` [PATCH RFC 07/10] KVM: VMX: Introduce ioctls to set/get Sub-Page Write Protection Zhang Yi
2017-10-13 23:14 ` [PATCH RFC 08/10] KVM: VMX: Update the EPT leaf entry indicated with the SPP enable bit Zhang Yi
2017-10-13 23:14 ` [PATCH RFC 09/10] KVM: VMX: Added setup spp page structure Zhang Yi
2017-10-13 23:16 ` [PATCH RFC 10/10] KVM: VMX: implement setup SPP page structure in spp miss Zhang Yi
2017-10-18 7:09 ` [PATCH RFC 00/10] Intel EPT-Based Sub-page Write Protection Support Christoph Hellwig
2017-10-18 14:02 ` Yi Zhang [this message]
2017-11-04 0:12 ` Yi Zhang
2017-11-04 16:54 ` Paolo Bonzini
2017-11-10 15:39 ` Paolo Bonzini
2017-11-13 10:37 ` Yi Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171018140247.GA28204@dazhang1-ssd.sh.intel.com \
--to=yi.z.zhang@linux.intel.com \
--cc=hch@infradead.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=rkrcmar@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®