* [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm
@ 2010-03-01 14:34 Joerg Roedel
2010-03-01 14:34 ` [PATCH 1/7] KVM: SVM: Return correct values in nested_svm_exit_handled_msr Joerg Roedel
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: Alexander Graf, kvm, linux-kernel
Hi,
this is the third round of the msrpm merge optimization patches for
nested svm. The change to the previous post it the introduction of an
direc_access_msrs list which contains all msrs that a guest might
directly access. This list is used to initialize the msrpm bitmaps and
the msrpm_offset table used for merging two tables. This optimization
more than doubles the performance of kernel compiles in the nested guest
using nested-shadow paging.
The other random fixes in this set were not changed to the last version
of this set. Patch 1/7 is new because it was forgotten in the last post.
Thanks,
Joerg
Diffstat:
arch/x86/kvm/svm.c | 259 +++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 195 insertions(+), 64 deletions(-)
Shortlog:
Joerg Roedel (7):
KVM: SVM: Return correct values in nested_svm_exit_handled_msr
KVM: SVM: Move msrpm offset calculation to seperate function
KVM: SVM: Introduce direct access msr list
KVM: SVM: Optimize nested svm msrpm merging
KVM: SVM: Use svm_msrpm_offset in nested_svm_exit_handled_msr
KVM; SVM: Add correct handling of nested iopm
KVM: SVM: Ignore lower 12 bit of nested msrpm_pa
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] KVM: SVM: Return correct values in nested_svm_exit_handled_msr
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-01 14:34 ` [PATCH 2/7] KVM: SVM: Move msrpm offset calculation to seperate function Joerg Roedel
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
The nested_svm_exit_handled_msr() returned an bool which is
a bug. I worked by accident because the exected integer
return values match with the true and false values. This
patch changes the return value to int and let the function
return the correct values.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 1397877..9dfbbae 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1546,16 +1546,16 @@ static void nested_svm_unmap(struct page *page)
kvm_release_page_dirty(page);
}
-static bool nested_svm_exit_handled_msr(struct vcpu_svm *svm)
+static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
{
u32 param = svm->vmcb->control.exit_info_1 & 1;
u32 msr = svm->vcpu.arch.regs[VCPU_REGS_RCX];
- bool ret = false;
u32 t0, t1;
+ int ret;
u8 val;
if (!(svm->nested.intercept & (1ULL << INTERCEPT_MSR_PROT)))
- return false;
+ return NESTED_EXIT_HOST;
switch (msr) {
case 0 ... 0x1fff:
@@ -1573,12 +1573,12 @@ static bool nested_svm_exit_handled_msr(struct vcpu_svm *svm)
t0 %= 8;
break;
default:
- ret = true;
+ ret = NESTED_EXIT_DONE;
goto out;
}
if (!kvm_read_guest(svm->vcpu.kvm, svm->nested.vmcb_msrpm + t1, &val, 1))
- ret = val & ((1 << param) << t0);
+ ret = val & ((1 << param) << t0) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
out:
return ret;
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/7] KVM: SVM: Move msrpm offset calculation to seperate function
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
2010-03-01 14:34 ` [PATCH 1/7] KVM: SVM: Return correct values in nested_svm_exit_handled_msr Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-01 14:34 ` [PATCH 3/7] KVM: SVM: Introduce direct access msr list Joerg Roedel
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
The algorithm to find the offset in the msrpm for a given
msr is needed at other places too. Move that logic to its
own function.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 53 ++++++++++++++++++++++++++++++++++++---------------
1 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 9dfbbae..c0c01a8 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -116,6 +116,8 @@ struct vcpu_svm {
unsigned long int3_rip;
};
+#define MSR_INVALID 0xffffffffU
+
/* enable NPT for AMD64 and X86 with PAE */
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
static bool npt_enabled = true;
@@ -199,6 +201,27 @@ static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
#define MSRS_RANGE_SIZE 2048
#define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
+static u32 svm_msrpm_offset(u32 msr)
+{
+ u32 offset;
+ int i;
+
+ for (i = 0; i < NUM_MSR_MAPS; i++) {
+ if (msr < msrpm_ranges[i] ||
+ msr >= msrpm_ranges[i] + MSRS_IN_RANGE)
+ continue;
+
+ offset = (msr - msrpm_ranges[i]) / 4; /* 4 msrs per u8 */
+ offset += (i * MSRS_RANGE_SIZE); /* add range offset */
+
+ /* Now we have the u8 offset - but need the u32 offset */
+ return offset / 4;
+ }
+
+ /* MSR not in any range */
+ return MSR_INVALID;
+}
+
#define MAX_INST_SIZE 15
static inline u32 svm_has(u32 feat)
@@ -417,23 +440,21 @@ err_1:
static void set_msr_interception(u32 *msrpm, unsigned msr,
int read, int write)
{
- int i;
+ u8 bit_read, bit_write;
+ unsigned long tmp;
+ u32 offset;
- for (i = 0; i < NUM_MSR_MAPS; i++) {
- if (msr >= msrpm_ranges[i] &&
- msr < msrpm_ranges[i] + MSRS_IN_RANGE) {
- u32 msr_offset = (i * MSRS_IN_RANGE + msr -
- msrpm_ranges[i]) * 2;
-
- u32 *base = msrpm + (msr_offset / 32);
- u32 msr_shift = msr_offset % 32;
- u32 mask = ((write) ? 0 : 2) | ((read) ? 0 : 1);
- *base = (*base & ~(0x3 << msr_shift)) |
- (mask << msr_shift);
- return;
- }
- }
- BUG();
+ offset = svm_msrpm_offset(msr);
+ bit_read = 2 * (msr & 0x0f);
+ bit_write = 2 * (msr & 0x0f) + 1;
+ tmp = msrpm[offset];
+
+ BUG_ON(offset == MSR_INVALID);
+
+ read ? clear_bit(bit_read, &tmp) : set_bit(bit_read, &tmp);
+ write ? clear_bit(bit_write, &tmp) : set_bit(bit_write, &tmp);
+
+ msrpm[offset] = tmp;
}
static void svm_vcpu_init_msrpm(u32 *msrpm)
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/7] KVM: SVM: Introduce direct access msr list
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
2010-03-01 14:34 ` [PATCH 1/7] KVM: SVM: Return correct values in nested_svm_exit_handled_msr Joerg Roedel
2010-03-01 14:34 ` [PATCH 2/7] KVM: SVM: Move msrpm offset calculation to seperate function Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-01 14:34 ` [PATCH 4/7] KVM: SVM: Optimize nested svm msrpm merging Joerg Roedel
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
This patch introduces a list with all msrs a guest might
have direct access to and changes the svm_vcpu_init_msrpm
function to use this list.
It also adds a check to set_msr_interception which triggers
a warning if a developer changes a msr intercept that is not
in the list.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 56 ++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index c0c01a8..18d7938 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -118,6 +118,27 @@ struct vcpu_svm {
#define MSR_INVALID 0xffffffffU
+static struct svm_direct_access_msrs {
+ u32 index; /* Index of the MSR */
+ bool always; /* True if intercept is always on */
+} direct_access_msrs[] = {
+ { .index = MSR_K6_STAR, .always = true },
+ { .index = MSR_IA32_SYSENTER_CS, .always = true },
+#ifdef CONFIG_X86_64
+ { .index = MSR_GS_BASE, .always = true },
+ { .index = MSR_FS_BASE, .always = true },
+ { .index = MSR_KERNEL_GS_BASE, .always = true },
+ { .index = MSR_LSTAR, .always = true },
+ { .index = MSR_CSTAR, .always = true },
+ { .index = MSR_SYSCALL_MASK, .always = true },
+#endif
+ { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
+ { .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
+ { .index = MSR_IA32_LASTINTFROMIP, .always = false },
+ { .index = MSR_IA32_LASTINTTOIP, .always = false },
+ { .index = MSR_INVALID, .always = false },
+};
+
/* enable NPT for AMD64 and X86 with PAE */
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
static bool npt_enabled = true;
@@ -437,6 +458,17 @@ err_1:
}
+static bool valid_msr_intercept(u32 index)
+{
+ int i;
+
+ for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++)
+ if (direct_access_msrs[i].index == index)
+ return true;
+
+ return false;
+}
+
static void set_msr_interception(u32 *msrpm, unsigned msr,
int read, int write)
{
@@ -444,6 +476,12 @@ static void set_msr_interception(u32 *msrpm, unsigned msr,
unsigned long tmp;
u32 offset;
+ /*
+ * If this warning triggers extend the direct_access_msrs list at the
+ * beginning of the file
+ */
+ WARN_ON(!valid_msr_intercept(msr));
+
offset = svm_msrpm_offset(msr);
bit_read = 2 * (msr & 0x0f);
bit_write = 2 * (msr & 0x0f) + 1;
@@ -459,18 +497,16 @@ static void set_msr_interception(u32 *msrpm, unsigned msr,
static void svm_vcpu_init_msrpm(u32 *msrpm)
{
+ int i;
+
memset(msrpm, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
-#ifdef CONFIG_X86_64
- set_msr_interception(msrpm, MSR_GS_BASE, 1, 1);
- set_msr_interception(msrpm, MSR_FS_BASE, 1, 1);
- set_msr_interception(msrpm, MSR_KERNEL_GS_BASE, 1, 1);
- set_msr_interception(msrpm, MSR_LSTAR, 1, 1);
- set_msr_interception(msrpm, MSR_CSTAR, 1, 1);
- set_msr_interception(msrpm, MSR_SYSCALL_MASK, 1, 1);
-#endif
- set_msr_interception(msrpm, MSR_K6_STAR, 1, 1);
- set_msr_interception(msrpm, MSR_IA32_SYSENTER_CS, 1, 1);
+ for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
+ if (!direct_access_msrs[i].always)
+ continue;
+
+ set_msr_interception(msrpm, direct_access_msrs[i].index, 1, 1);
+ }
}
static void svm_enable_lbrv(struct vcpu_svm *svm)
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/7] KVM: SVM: Optimize nested svm msrpm merging
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
` (2 preceding siblings ...)
2010-03-01 14:34 ` [PATCH 3/7] KVM: SVM: Introduce direct access msr list Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-01 14:34 ` [PATCH 5/7] KVM: SVM: Use svm_msrpm_offset in nested_svm_exit_handled_msr Joerg Roedel
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
This patch optimizes the way the msrpm of the host and the
guest are merged. The old code merged the 2 msrpm pages
completly. This code needed to touch 24kb of memory for that
operation. The optimized variant this patch introduces
merges only the parts where the host msrpm may contain zero
bits. This reduces the amount of memory which is touched to
48 bytes.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 71 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 18d7938..c04ce1e 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -92,6 +92,9 @@ struct nested_state {
};
+#define MSRPM_OFFSETS 16
+static u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
+
struct vcpu_svm {
struct kvm_vcpu vcpu;
struct vmcb *vmcb;
@@ -509,6 +512,49 @@ static void svm_vcpu_init_msrpm(u32 *msrpm)
}
}
+static void add_msr_offset(u32 offset)
+{
+ int i;
+
+ for (i = 0; i < MSRPM_OFFSETS; ++i) {
+
+ /* Offset already in list? */
+ if (msrpm_offsets[i] == offset)
+ return;
+
+ /* Slot used by another offset? */
+ if (msrpm_offsets[i] != MSR_INVALID)
+ continue;
+
+ /* Add offset to list */
+ msrpm_offsets[i] = offset;
+
+ return;
+ }
+
+ /*
+ * If this BUG triggers the msrpm_offsets table has an overflow. Just
+ * increase MSRPM_OFFSETS in this case.
+ */
+ BUG();
+}
+
+static void init_msrpm_offsets(void)
+{
+ int i;
+
+ memset(msrpm_offsets, 0xff, sizeof(msrpm_offsets));
+
+ for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
+ u32 offset;
+
+ offset = svm_msrpm_offset(direct_access_msrs[i].index);
+ BUG_ON(offset == MSR_INVALID);
+
+ add_msr_offset(offset);
+ }
+}
+
static void svm_enable_lbrv(struct vcpu_svm *svm)
{
u32 *msrpm = svm->msrpm;
@@ -547,6 +593,8 @@ static __init int svm_hardware_setup(void)
memset(iopm_va, 0xff, PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
+ init_msrpm_offsets();
+
if (boot_cpu_has(X86_FEATURE_NX))
kvm_enable_efer_bits(EFER_NX);
@@ -811,6 +859,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
svm->nested.hsave = page_address(hsave_page);
svm->nested.msrpm = page_address(nested_msrpm_pages);
+ svm_vcpu_init_msrpm(svm->nested.msrpm);
svm->vmcb = page_address(page);
clear_page(svm->vmcb);
@@ -1882,20 +1931,33 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
{
- u32 *nested_msrpm;
- struct page *page;
+ /*
+ * This function merges the msr permission bitmaps of kvm and the
+ * nested vmcb. It is omptimized in that it only merges the parts where
+ * the kvm msr permission bitmap may contain zero bits
+ */
int i;
- nested_msrpm = nested_svm_map(svm, svm->nested.vmcb_msrpm, &page);
- if (!nested_msrpm)
- return false;
+ if (!(svm->nested.intercept & (1ULL << INTERCEPT_MSR_PROT)))
+ return true;
- for (i = 0; i < PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER) / 4; i++)
- svm->nested.msrpm[i] = svm->msrpm[i] | nested_msrpm[i];
+ for (i = 0; i < MSRPM_OFFSETS; i++) {
+ u32 value, p;
+ u64 offset;
- svm->vmcb->control.msrpm_base_pa = __pa(svm->nested.msrpm);
+ if (msrpm_offsets[i] == 0xffffffff)
+ break;
- nested_svm_unmap(page);
+ offset = svm->nested.vmcb_msrpm + msrpm_offsets[i];
+ p = msrpm_offsets[i] / 4;
+
+ if (kvm_read_guest(svm->vcpu.kvm, offset, &value, 4))
+ return false;
+
+ svm->nested.msrpm[p] = svm->msrpm[p] | value;
+ }
+
+ svm->vmcb->control.msrpm_base_pa = __pa(svm->nested.msrpm);
return true;
}
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/7] KVM: SVM: Use svm_msrpm_offset in nested_svm_exit_handled_msr
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
` (3 preceding siblings ...)
2010-03-01 14:34 ` [PATCH 4/7] KVM: SVM: Optimize nested svm msrpm merging Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-01 14:34 ` [PATCH 6/7] KVM; SVM: Add correct handling of nested iopm Joerg Roedel
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
There is a generic function now to calculate msrpm offsets.
Use that function in nested_svm_exit_handled_msr() remove
the duplicate logic (which had a bug anyway).
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 47 +++++++++++++++++------------------------------
1 files changed, 17 insertions(+), 30 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index c04ce1e..b705115 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1654,40 +1654,27 @@ static void nested_svm_unmap(struct page *page)
static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
{
- u32 param = svm->vmcb->control.exit_info_1 & 1;
- u32 msr = svm->vcpu.arch.regs[VCPU_REGS_RCX];
- u32 t0, t1;
- int ret;
- u8 val;
+ u32 offset, msr, value;
+ int write, mask;
if (!(svm->nested.intercept & (1ULL << INTERCEPT_MSR_PROT)))
return NESTED_EXIT_HOST;
- switch (msr) {
- case 0 ... 0x1fff:
- t0 = (msr * 2) % 8;
- t1 = msr / 8;
- break;
- case 0xc0000000 ... 0xc0001fff:
- t0 = (8192 + msr - 0xc0000000) * 2;
- t1 = (t0 / 8);
- t0 %= 8;
- break;
- case 0xc0010000 ... 0xc0011fff:
- t0 = (16384 + msr - 0xc0010000) * 2;
- t1 = (t0 / 8);
- t0 %= 8;
- break;
- default:
- ret = NESTED_EXIT_DONE;
- goto out;
- }
+ msr = svm->vcpu.arch.regs[VCPU_REGS_RCX];
+ offset = svm_msrpm_offset(msr);
+ write = svm->vmcb->control.exit_info_1 & 1;
+ mask = 1 << ((2 * (msr & 0xf)) + write);
- if (!kvm_read_guest(svm->vcpu.kvm, svm->nested.vmcb_msrpm + t1, &val, 1))
- ret = val & ((1 << param) << t0) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
+ if (offset == MSR_INVALID)
+ return NESTED_EXIT_DONE;
-out:
- return ret;
+ /* Offset is in 32 bit units but need in 8 bit units */
+ offset *= 4;
+
+ if (kvm_read_guest(svm->vcpu.kvm, svm->nested.vmcb_msrpm + offset, &value, 4))
+ return NESTED_EXIT_DONE;
+
+ return (value & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
}
static int nested_svm_exit_special(struct vcpu_svm *svm)
@@ -1948,8 +1935,8 @@ static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
if (msrpm_offsets[i] == 0xffffffff)
break;
- offset = svm->nested.vmcb_msrpm + msrpm_offsets[i];
- p = msrpm_offsets[i] / 4;
+ p = msrpm_offsets[i];
+ offset = svm->nested.vmcb_msrpm + (p * 4);
if (kvm_read_guest(svm->vcpu.kvm, offset, &value, 4))
return false;
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/7] KVM; SVM: Add correct handling of nested iopm
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
` (4 preceding siblings ...)
2010-03-01 14:34 ` [PATCH 5/7] KVM: SVM: Use svm_msrpm_offset in nested_svm_exit_handled_msr Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-01 14:34 ` [PATCH 7/7] KVM: SVM: Ignore lower 12 bit of nested msrpm_pa Joerg Roedel
2010-03-02 14:26 ` [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Marcelo Tosatti
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
This patch adds the correct handling of the nested io
permission bitmap. Old behavior was to not lookup the port
in the iopm but only reinject an io intercept to the guest.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index b705115..eb3bfa4 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -78,6 +78,7 @@ struct nested_state {
/* gpa pointers to the real vectors */
u64 vmcb_msrpm;
+ u64 vmcb_iopm;
/* A VMEXIT is required but not yet emulated */
bool exit_required;
@@ -1652,6 +1653,26 @@ static void nested_svm_unmap(struct page *page)
kvm_release_page_dirty(page);
}
+static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
+{
+ unsigned port;
+ u8 val, bit;
+ u64 gpa;
+
+ if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT)))
+ return NESTED_EXIT_HOST;
+
+ port = svm->vmcb->control.exit_info_1 >> 16;
+ gpa = svm->nested.vmcb_iopm + (port / 8);
+ bit = port % 8;
+ val = 0;
+
+ if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, 1))
+ val &= (1 << bit);
+
+ return val ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
+}
+
static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
{
u32 offset, msr, value;
@@ -1717,6 +1738,9 @@ static int nested_svm_intercept(struct vcpu_svm *svm)
case SVM_EXIT_MSR:
vmexit = nested_svm_exit_handled_msr(svm);
break;
+ case SVM_EXIT_IOIO:
+ vmexit = nested_svm_intercept_ioio(svm);
+ break;
case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: {
u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0);
if (svm->nested.intercept_cr_read & cr_bits)
@@ -2041,6 +2065,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
svm->vmcb->save.cpl = nested_vmcb->save.cpl;
svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa;
+ svm->nested.vmcb_iopm = nested_vmcb->control.iopm_base_pa & ~0x0fffULL;
/* cache intercepts */
svm->nested.intercept_cr_read = nested_vmcb->control.intercept_cr_read;
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 7/7] KVM: SVM: Ignore lower 12 bit of nested msrpm_pa
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
` (5 preceding siblings ...)
2010-03-01 14:34 ` [PATCH 6/7] KVM; SVM: Add correct handling of nested iopm Joerg Roedel
@ 2010-03-01 14:34 ` Joerg Roedel
2010-03-02 14:26 ` [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Marcelo Tosatti
7 siblings, 0 replies; 9+ messages in thread
From: Joerg Roedel @ 2010-03-01 14:34 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: Alexander Graf, kvm, linux-kernel, Joerg Roedel
These bits are ignored by the hardware too. Implement this
for nested svm too.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kvm/svm.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index eb3bfa4..def4877 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2064,7 +2064,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
svm->vmcb->save.dr6 = nested_vmcb->save.dr6;
svm->vmcb->save.cpl = nested_vmcb->save.cpl;
- svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa;
+ svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa & ~0x0fffULL;
svm->nested.vmcb_iopm = nested_vmcb->control.iopm_base_pa & ~0x0fffULL;
/* cache intercepts */
--
1.7.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
` (6 preceding siblings ...)
2010-03-01 14:34 ` [PATCH 7/7] KVM: SVM: Ignore lower 12 bit of nested msrpm_pa Joerg Roedel
@ 2010-03-02 14:26 ` Marcelo Tosatti
7 siblings, 0 replies; 9+ messages in thread
From: Marcelo Tosatti @ 2010-03-02 14:26 UTC (permalink / raw)
To: Joerg Roedel; +Cc: Avi Kivity, Alexander Graf, kvm, linux-kernel
On Mon, Mar 01, 2010 at 03:34:33PM +0100, Joerg Roedel wrote:
> Hi,
>
> this is the third round of the msrpm merge optimization patches for
> nested svm. The change to the previous post it the introduction of an
> direc_access_msrs list which contains all msrs that a guest might
> directly access. This list is used to initialize the msrpm bitmaps and
> the msrpm_offset table used for merging two tables. This optimization
> more than doubles the performance of kernel compiles in the nested guest
> using nested-shadow paging.
> The other random fixes in this set were not changed to the last version
> of this set. Patch 1/7 is new because it was forgotten in the last post.
>
> Thanks,
>
> Joerg
Applied, thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-03-02 14:32 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-01 14:34 [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Joerg Roedel
2010-03-01 14:34 ` [PATCH 1/7] KVM: SVM: Return correct values in nested_svm_exit_handled_msr Joerg Roedel
2010-03-01 14:34 ` [PATCH 2/7] KVM: SVM: Move msrpm offset calculation to seperate function Joerg Roedel
2010-03-01 14:34 ` [PATCH 3/7] KVM: SVM: Introduce direct access msr list Joerg Roedel
2010-03-01 14:34 ` [PATCH 4/7] KVM: SVM: Optimize nested svm msrpm merging Joerg Roedel
2010-03-01 14:34 ` [PATCH 5/7] KVM: SVM: Use svm_msrpm_offset in nested_svm_exit_handled_msr Joerg Roedel
2010-03-01 14:34 ` [PATCH 6/7] KVM; SVM: Add correct handling of nested iopm Joerg Roedel
2010-03-01 14:34 ` [PATCH 7/7] KVM: SVM: Ignore lower 12 bit of nested msrpm_pa Joerg Roedel
2010-03-02 14:26 ` [PATCH 0/7 v3] Rework of msrpm optimization and additional fixes for nested svm Marcelo Tosatti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox