mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM changes from Paolo Bonzini: "Here are the 3.13 KVM changes. There was a lot of work on the PPC side: the HV and emulation flavors can now coexist in a single kernel is probably the most interesting change from a user point of view. On the x86 side there are nested virtualization improvements and a few bugfixes. ARM got transparent huge page support, improved overcommit, and support for big endian guests. Finally, there is a new interface to connect KVM with VFIO. This helps with devices that use NoSnoop PCI transactions, letting the driver in the guest execute WBINVD instructions. This includes some nVidia cards on Windows, that fail to start without these patches and the corresponding userspace changes" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (146 commits) kvm, vmx: Fix lazy FPU on nested guest arm/arm64: KVM: PSCI: propagate caller endianness to the incoming vcpu arm/arm64: KVM: MMIO support for BE guest kvm, cpuid: Fix sparse warning kvm: Delete prototype for non-existent function kvm_check_iopl kvm: Delete prototype for non-existent function complete_pio hung_task: add method to reset detector pvclock: detect watchdog reset at pvclock read kvm: optimize out smp_mb after srcu_read_unlock srcu: API for barrier after srcu read unlock KVM: remove vm mmap method KVM: IOMMU: hva align mapping page size KVM: x86: trace cpuid emulation when called from emulator KVM: emulator: cleanup decode_register_operand() a bit KVM: emulator: check rex prefix inside decode_register() KVM: x86: fix emulation of "movzbl %bpl, %eax" kvm_host: typo fix KVM: x86: emulate SAHF instruction MAINTAINERS: add tree for kvm.git Documentation/kvm: add a 00-INDEX file ...
This commit is contained in:
24
Documentation/virtual/kvm/00-INDEX
Normal file
24
Documentation/virtual/kvm/00-INDEX
Normal file
@@ -0,0 +1,24 @@
|
||||
00-INDEX
|
||||
- this file.
|
||||
api.txt
|
||||
- KVM userspace API.
|
||||
cpuid.txt
|
||||
- KVM-specific cpuid leaves (x86).
|
||||
devices/
|
||||
- KVM_CAP_DEVICE_CTRL userspace API.
|
||||
hypercalls.txt
|
||||
- KVM hypercalls.
|
||||
locking.txt
|
||||
- notes on KVM locks.
|
||||
mmu.txt
|
||||
- the x86 kvm shadow mmu.
|
||||
msr.txt
|
||||
- KVM-specific MSRs (x86).
|
||||
nested-vmx.txt
|
||||
- notes on nested virtualization for Intel x86 processors.
|
||||
ppc-pv.txt
|
||||
- the paravirtualization interface on PowerPC.
|
||||
review-checklist.txt
|
||||
- review checklist for KVM patches.
|
||||
timekeeping.txt
|
||||
- timekeeping virtualization for x86-based architectures.
|
||||
@@ -1122,9 +1122,9 @@ struct kvm_cpuid2 {
|
||||
struct kvm_cpuid_entry2 entries[0];
|
||||
};
|
||||
|
||||
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
|
||||
#define KVM_CPUID_FLAG_STATEFUL_FUNC 2
|
||||
#define KVM_CPUID_FLAG_STATE_READ_NEXT 4
|
||||
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
|
||||
#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1)
|
||||
#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2)
|
||||
|
||||
struct kvm_cpuid_entry2 {
|
||||
__u32 function;
|
||||
@@ -1810,6 +1810,50 @@ registers, find a list below:
|
||||
PPC | KVM_REG_PPC_TLB3PS | 32
|
||||
PPC | KVM_REG_PPC_EPTCFG | 32
|
||||
PPC | KVM_REG_PPC_ICP_STATE | 64
|
||||
PPC | KVM_REG_PPC_TB_OFFSET | 64
|
||||
PPC | KVM_REG_PPC_SPMC1 | 32
|
||||
PPC | KVM_REG_PPC_SPMC2 | 32
|
||||
PPC | KVM_REG_PPC_IAMR | 64
|
||||
PPC | KVM_REG_PPC_TFHAR | 64
|
||||
PPC | KVM_REG_PPC_TFIAR | 64
|
||||
PPC | KVM_REG_PPC_TEXASR | 64
|
||||
PPC | KVM_REG_PPC_FSCR | 64
|
||||
PPC | KVM_REG_PPC_PSPB | 32
|
||||
PPC | KVM_REG_PPC_EBBHR | 64
|
||||
PPC | KVM_REG_PPC_EBBRR | 64
|
||||
PPC | KVM_REG_PPC_BESCR | 64
|
||||
PPC | KVM_REG_PPC_TAR | 64
|
||||
PPC | KVM_REG_PPC_DPDES | 64
|
||||
PPC | KVM_REG_PPC_DAWR | 64
|
||||
PPC | KVM_REG_PPC_DAWRX | 64
|
||||
PPC | KVM_REG_PPC_CIABR | 64
|
||||
PPC | KVM_REG_PPC_IC | 64
|
||||
PPC | KVM_REG_PPC_VTB | 64
|
||||
PPC | KVM_REG_PPC_CSIGR | 64
|
||||
PPC | KVM_REG_PPC_TACR | 64
|
||||
PPC | KVM_REG_PPC_TCSCR | 64
|
||||
PPC | KVM_REG_PPC_PID | 64
|
||||
PPC | KVM_REG_PPC_ACOP | 64
|
||||
PPC | KVM_REG_PPC_VRSAVE | 32
|
||||
PPC | KVM_REG_PPC_LPCR | 64
|
||||
PPC | KVM_REG_PPC_PPR | 64
|
||||
PPC | KVM_REG_PPC_ARCH_COMPAT 32
|
||||
PPC | KVM_REG_PPC_TM_GPR0 | 64
|
||||
...
|
||||
PPC | KVM_REG_PPC_TM_GPR31 | 64
|
||||
PPC | KVM_REG_PPC_TM_VSR0 | 128
|
||||
...
|
||||
PPC | KVM_REG_PPC_TM_VSR63 | 128
|
||||
PPC | KVM_REG_PPC_TM_CR | 64
|
||||
PPC | KVM_REG_PPC_TM_LR | 64
|
||||
PPC | KVM_REG_PPC_TM_CTR | 64
|
||||
PPC | KVM_REG_PPC_TM_FPSCR | 64
|
||||
PPC | KVM_REG_PPC_TM_AMR | 64
|
||||
PPC | KVM_REG_PPC_TM_PPR | 64
|
||||
PPC | KVM_REG_PPC_TM_VRSAVE | 64
|
||||
PPC | KVM_REG_PPC_TM_VSCR | 32
|
||||
PPC | KVM_REG_PPC_TM_DSCR | 64
|
||||
PPC | KVM_REG_PPC_TM_TAR | 64
|
||||
|
||||
ARM registers are mapped using the lower 32 bits. The upper 16 of that
|
||||
is the register group type, or coprocessor number:
|
||||
@@ -2304,7 +2348,31 @@ Possible features:
|
||||
Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
|
||||
|
||||
|
||||
4.83 KVM_GET_REG_LIST
|
||||
4.83 KVM_ARM_PREFERRED_TARGET
|
||||
|
||||
Capability: basic
|
||||
Architectures: arm, arm64
|
||||
Type: vm ioctl
|
||||
Parameters: struct struct kvm_vcpu_init (out)
|
||||
Returns: 0 on success; -1 on error
|
||||
Errors:
|
||||
ENODEV: no preferred target available for the host
|
||||
|
||||
This queries KVM for preferred CPU target type which can be emulated
|
||||
by KVM on underlying host.
|
||||
|
||||
The ioctl returns struct kvm_vcpu_init instance containing information
|
||||
about preferred CPU target type and recommended features for it. The
|
||||
kvm_vcpu_init->features bitmap returned will have feature bits set if
|
||||
the preferred target recommends setting these features, but this is
|
||||
not mandatory.
|
||||
|
||||
The information returned by this ioctl can be used to prepare an instance
|
||||
of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
|
||||
in VCPU matching underlying host.
|
||||
|
||||
|
||||
4.84 KVM_GET_REG_LIST
|
||||
|
||||
Capability: basic
|
||||
Architectures: arm, arm64
|
||||
@@ -2323,8 +2391,7 @@ struct kvm_reg_list {
|
||||
This ioctl returns the guest registers that are supported for the
|
||||
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
|
||||
|
||||
|
||||
4.84 KVM_ARM_SET_DEVICE_ADDR
|
||||
4.85 KVM_ARM_SET_DEVICE_ADDR
|
||||
|
||||
Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
|
||||
Architectures: arm, arm64
|
||||
@@ -2362,7 +2429,7 @@ must be called after calling KVM_CREATE_IRQCHIP, but before calling
|
||||
KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the
|
||||
base addresses will return -EEXIST.
|
||||
|
||||
4.85 KVM_PPC_RTAS_DEFINE_TOKEN
|
||||
4.86 KVM_PPC_RTAS_DEFINE_TOKEN
|
||||
|
||||
Capability: KVM_CAP_PPC_RTAS
|
||||
Architectures: ppc
|
||||
@@ -2661,6 +2728,77 @@ and usually define the validity of a groups of registers. (e.g. one bit
|
||||
};
|
||||
|
||||
|
||||
4.81 KVM_GET_EMULATED_CPUID
|
||||
|
||||
Capability: KVM_CAP_EXT_EMUL_CPUID
|
||||
Architectures: x86
|
||||
Type: system ioctl
|
||||
Parameters: struct kvm_cpuid2 (in/out)
|
||||
Returns: 0 on success, -1 on error
|
||||
|
||||
struct kvm_cpuid2 {
|
||||
__u32 nent;
|
||||
__u32 flags;
|
||||
struct kvm_cpuid_entry2 entries[0];
|
||||
};
|
||||
|
||||
The member 'flags' is used for passing flags from userspace.
|
||||
|
||||
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
|
||||
#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1)
|
||||
#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2)
|
||||
|
||||
struct kvm_cpuid_entry2 {
|
||||
__u32 function;
|
||||
__u32 index;
|
||||
__u32 flags;
|
||||
__u32 eax;
|
||||
__u32 ebx;
|
||||
__u32 ecx;
|
||||
__u32 edx;
|
||||
__u32 padding[3];
|
||||
};
|
||||
|
||||
This ioctl returns x86 cpuid features which are emulated by
|
||||
kvm.Userspace can use the information returned by this ioctl to query
|
||||
which features are emulated by kvm instead of being present natively.
|
||||
|
||||
Userspace invokes KVM_GET_EMULATED_CPUID by passing a kvm_cpuid2
|
||||
structure with the 'nent' field indicating the number of entries in
|
||||
the variable-size array 'entries'. If the number of entries is too low
|
||||
to describe the cpu capabilities, an error (E2BIG) is returned. If the
|
||||
number is too high, the 'nent' field is adjusted and an error (ENOMEM)
|
||||
is returned. If the number is just right, the 'nent' field is adjusted
|
||||
to the number of valid entries in the 'entries' array, which is then
|
||||
filled.
|
||||
|
||||
The entries returned are the set CPUID bits of the respective features
|
||||
which kvm emulates, as returned by the CPUID instruction, with unknown
|
||||
or unsupported feature bits cleared.
|
||||
|
||||
Features like x2apic, for example, may not be present in the host cpu
|
||||
but are exposed by kvm in KVM_GET_SUPPORTED_CPUID because they can be
|
||||
emulated efficiently and thus not included here.
|
||||
|
||||
The fields in each entry are defined as follows:
|
||||
|
||||
function: the eax value used to obtain the entry
|
||||
index: the ecx value used to obtain the entry (for entries that are
|
||||
affected by ecx)
|
||||
flags: an OR of zero or more of the following:
|
||||
KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
|
||||
if the index field is valid
|
||||
KVM_CPUID_FLAG_STATEFUL_FUNC:
|
||||
if cpuid for this function returns different values for successive
|
||||
invocations; there will be several entries with the same function,
|
||||
all with this flag set
|
||||
KVM_CPUID_FLAG_STATE_READ_NEXT:
|
||||
for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
|
||||
the first entry to be read by a cpu
|
||||
eax, ebx, ecx, edx: the values returned by the cpuid instruction for
|
||||
this function/index combination
|
||||
|
||||
|
||||
6. Capabilities that can be enabled
|
||||
-----------------------------------
|
||||
|
||||
|
||||
@@ -43,6 +43,13 @@ KVM_FEATURE_CLOCKSOURCE2 || 3 || kvmclock available at msrs
|
||||
KVM_FEATURE_ASYNC_PF || 4 || async pf can be enabled by
|
||||
|| || writing to msr 0x4b564d02
|
||||
------------------------------------------------------------------------------
|
||||
KVM_FEATURE_STEAL_TIME || 5 || steal time can be enabled by
|
||||
|| || writing to msr 0x4b564d03.
|
||||
------------------------------------------------------------------------------
|
||||
KVM_FEATURE_PV_EOI || 6 || paravirtualized end of interrupt
|
||||
|| || handler can be enabled by writing
|
||||
|| || to msr 0x4b564d04.
|
||||
------------------------------------------------------------------------------
|
||||
KVM_FEATURE_PV_UNHALT || 7 || guest checks this feature bit
|
||||
|| || before enabling paravirtualized
|
||||
|| || spinlock support.
|
||||
|
||||
22
Documentation/virtual/kvm/devices/vfio.txt
Normal file
22
Documentation/virtual/kvm/devices/vfio.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
VFIO virtual device
|
||||
===================
|
||||
|
||||
Device types supported:
|
||||
KVM_DEV_TYPE_VFIO
|
||||
|
||||
Only one VFIO instance may be created per VM. The created device
|
||||
tracks VFIO groups in use by the VM and features of those groups
|
||||
important to the correctness and acceleration of the VM. As groups
|
||||
are enabled and disabled for use by the VM, KVM should be updated
|
||||
about their presence. When registered with KVM, a reference to the
|
||||
VFIO-group is held by KVM.
|
||||
|
||||
Groups:
|
||||
KVM_DEV_VFIO_GROUP
|
||||
|
||||
KVM_DEV_VFIO_GROUP attributes:
|
||||
KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
|
||||
KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
|
||||
|
||||
For each, kvm_device_attr.addr points to an int32_t file descriptor
|
||||
for the VFIO group.
|
||||
@@ -132,10 +132,14 @@ See the comments in spte_has_volatile_bits() and mmu_spte_update().
|
||||
------------
|
||||
|
||||
Name: kvm_lock
|
||||
Type: raw_spinlock
|
||||
Type: spinlock_t
|
||||
Arch: any
|
||||
Protects: - vm_list
|
||||
- hardware virtualization enable/disable
|
||||
|
||||
Name: kvm_count_lock
|
||||
Type: raw_spinlock_t
|
||||
Arch: any
|
||||
Protects: - hardware virtualization enable/disable
|
||||
Comment: 'raw' because hardware enabling/disabling must be atomic /wrt
|
||||
migration.
|
||||
|
||||
@@ -151,3 +155,14 @@ Type: spinlock_t
|
||||
Arch: any
|
||||
Protects: -shadow page/shadow tlb entry
|
||||
Comment: it is a spinlock since it is used in mmu notifier.
|
||||
|
||||
Name: kvm->srcu
|
||||
Type: srcu lock
|
||||
Arch: any
|
||||
Protects: - kvm->memslots
|
||||
- kvm->buses
|
||||
Comment: The srcu read lock must be held while accessing memslots (e.g.
|
||||
when using gfn_to_* functions) and while accessing in-kernel
|
||||
MMIO/PIO address->device structure mapping (kvm->buses).
|
||||
The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
|
||||
if it is needed by multiple functions.
|
||||
|
||||
@@ -4871,7 +4871,8 @@ KERNEL VIRTUAL MACHINE (KVM)
|
||||
M: Gleb Natapov <gleb@redhat.com>
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
L: kvm@vger.kernel.org
|
||||
W: http://linux-kvm.org
|
||||
W: http://www.linux-kvm.org
|
||||
T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
|
||||
S: Supported
|
||||
F: Documentation/*/kvm*.txt
|
||||
F: Documentation/virtual/kvm/
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
* TSC: Trap SMC
|
||||
* TSW: Trap cache operations by set/way
|
||||
* TWI: Trap WFI
|
||||
* TWE: Trap WFE
|
||||
* TIDCP: Trap L2CTLR/L2ECTLR
|
||||
* BSU_IS: Upgrade barriers to the inner shareable domain
|
||||
* FB: Force broadcast of all maintainance operations
|
||||
@@ -67,7 +68,7 @@
|
||||
*/
|
||||
#define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
|
||||
HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
|
||||
HCR_SWIO | HCR_TIDCP)
|
||||
HCR_TWE | HCR_SWIO | HCR_TIDCP)
|
||||
#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
|
||||
|
||||
/* System Control Register (SCTLR) bits */
|
||||
@@ -95,12 +96,12 @@
|
||||
#define TTBCR_IRGN1 (3 << 24)
|
||||
#define TTBCR_EPD1 (1 << 23)
|
||||
#define TTBCR_A1 (1 << 22)
|
||||
#define TTBCR_T1SZ (3 << 16)
|
||||
#define TTBCR_T1SZ (7 << 16)
|
||||
#define TTBCR_SH0 (3 << 12)
|
||||
#define TTBCR_ORGN0 (3 << 10)
|
||||
#define TTBCR_IRGN0 (3 << 8)
|
||||
#define TTBCR_EPD0 (1 << 7)
|
||||
#define TTBCR_T0SZ 3
|
||||
#define TTBCR_T0SZ (7 << 0)
|
||||
#define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
|
||||
|
||||
/* Hyp System Trap Register */
|
||||
@@ -208,6 +209,8 @@
|
||||
#define HSR_EC_DABT (0x24)
|
||||
#define HSR_EC_DABT_HYP (0x25)
|
||||
|
||||
#define HSR_WFI_IS_WFE (1U << 0)
|
||||
|
||||
#define HSR_HVC_IMM_MASK ((1UL << 16) - 1)
|
||||
|
||||
#define HSR_DABT_S1PTW (1U << 7)
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#define c6_IFAR 17 /* Instruction Fault Address Register */
|
||||
#define c7_PAR 18 /* Physical Address Register */
|
||||
#define c7_PAR_high 19 /* PAR top 32 bits */
|
||||
#define c9_L2CTLR 20 /* Cortex A15 L2 Control Register */
|
||||
#define c9_L2CTLR 20 /* Cortex A15/A7 L2 Control Register */
|
||||
#define c10_PRRR 21 /* Primary Region Remap Register */
|
||||
#define c10_NMRR 22 /* Normal Memory Remap Register */
|
||||
#define c12_VBAR 23 /* Vector Base Address Register */
|
||||
|
||||
@@ -157,4 +157,55 @@ static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
|
||||
return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return vcpu->arch.cp15[c0_MPIDR];
|
||||
}
|
||||
|
||||
static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
*vcpu_cpsr(vcpu) |= PSR_E_BIT;
|
||||
}
|
||||
|
||||
static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT);
|
||||
}
|
||||
|
||||
static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
|
||||
unsigned long data,
|
||||
unsigned int len)
|
||||
{
|
||||
if (kvm_vcpu_is_be(vcpu)) {
|
||||
switch (len) {
|
||||
case 1:
|
||||
return data & 0xff;
|
||||
case 2:
|
||||
return be16_to_cpu(data & 0xffff);
|
||||
default:
|
||||
return be32_to_cpu(data);
|
||||
}
|
||||
}
|
||||
|
||||
return data; /* Leave LE untouched */
|
||||
}
|
||||
|
||||
static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
|
||||
unsigned long data,
|
||||
unsigned int len)
|
||||
{
|
||||
if (kvm_vcpu_is_be(vcpu)) {
|
||||
switch (len) {
|
||||
case 1:
|
||||
return data & 0xff;
|
||||
case 2:
|
||||
return cpu_to_be16(data & 0xffff);
|
||||
default:
|
||||
return cpu_to_be32(data);
|
||||
}
|
||||
}
|
||||
|
||||
return data; /* Leave LE untouched */
|
||||
}
|
||||
|
||||
#endif /* __ARM_KVM_EMULATE_H__ */
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
|
||||
#define KVM_VCPU_MAX_FEATURES 1
|
||||
|
||||
/* We don't currently support large pages. */
|
||||
#define KVM_HPAGE_GFN_SHIFT(x) 0
|
||||
#define KVM_NR_PAGE_SIZES 1
|
||||
#define KVM_PAGES_PER_HPAGE(x) (1UL<<31)
|
||||
|
||||
#include <kvm/arm_vgic.h>
|
||||
|
||||
struct kvm_vcpu;
|
||||
@@ -154,6 +149,7 @@ struct kvm_vcpu_stat {
|
||||
struct kvm_vcpu_init;
|
||||
int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
|
||||
const struct kvm_vcpu_init *init);
|
||||
int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
|
||||
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
|
||||
int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
|
||||
struct kvm_one_reg;
|
||||
|
||||
@@ -62,6 +62,12 @@ phys_addr_t kvm_get_idmap_vector(void);
|
||||
int kvm_mmu_init(void);
|
||||
void kvm_clear_hyp_idmap(void);
|
||||
|
||||
static inline void kvm_set_pmd(pmd_t *pmd, pmd_t new_pmd)
|
||||
{
|
||||
*pmd = new_pmd;
|
||||
flush_pmd_entry(pmd);
|
||||
}
|
||||
|
||||
static inline void kvm_set_pte(pte_t *pte, pte_t new_pte)
|
||||
{
|
||||
*pte = new_pte;
|
||||
@@ -103,9 +109,15 @@ static inline void kvm_set_s2pte_writable(pte_t *pte)
|
||||
pte_val(*pte) |= L_PTE_S2_RDWR;
|
||||
}
|
||||
|
||||
static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
|
||||
{
|
||||
pmd_val(*pmd) |= L_PMD_S2_RDWR;
|
||||
}
|
||||
|
||||
struct kvm;
|
||||
|
||||
static inline void coherent_icache_guest_page(struct kvm *kvm, gfn_t gfn)
|
||||
static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva,
|
||||
unsigned long size)
|
||||
{
|
||||
/*
|
||||
* If we are going to insert an instruction page and the icache is
|
||||
@@ -120,8 +132,7 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, gfn_t gfn)
|
||||
* need any kind of flushing (DDI 0406C.b - Page B3-1392).
|
||||
*/
|
||||
if (icache_is_pipt()) {
|
||||
unsigned long hva = gfn_to_hva(kvm, gfn);
|
||||
__cpuc_coherent_user_range(hva, hva + PAGE_SIZE);
|
||||
__cpuc_coherent_user_range(hva, hva + size);
|
||||
} else if (!icache_is_vivt_asid_tagged()) {
|
||||
/* any kind of VIPT cache */
|
||||
__flush_icache_all();
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */
|
||||
#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */
|
||||
|
||||
#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */
|
||||
|
||||
/*
|
||||
* Hyp-mode PL2 PTE definitions for LPAE.
|
||||
*/
|
||||
|
||||
@@ -63,7 +63,8 @@ struct kvm_regs {
|
||||
|
||||
/* Supported Processor Types */
|
||||
#define KVM_ARM_TARGET_CORTEX_A15 0
|
||||
#define KVM_ARM_NUM_TARGETS 1
|
||||
#define KVM_ARM_TARGET_CORTEX_A7 1
|
||||
#define KVM_ARM_NUM_TARGETS 2
|
||||
|
||||
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
|
||||
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
|
||||
|
||||
@@ -20,6 +20,7 @@ config KVM
|
||||
bool "Kernel-based Virtual Machine (KVM) support"
|
||||
select PREEMPT_NOTIFIERS
|
||||
select ANON_INODES
|
||||
select HAVE_KVM_CPU_RELAX_INTERCEPT
|
||||
select KVM_MMIO
|
||||
select KVM_ARM_HOST
|
||||
depends on ARM_VIRT_EXT && ARM_LPAE
|
||||
|
||||
@@ -19,6 +19,6 @@ kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
|
||||
|
||||
obj-y += kvm-arm.o init.o interrupts.o
|
||||
obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
|
||||
obj-y += coproc.o coproc_a15.o mmio.o psci.o perf.o
|
||||
obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
|
||||
obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
|
||||
obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
|
||||
|
||||
@@ -152,12 +152,13 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
void kvm_arch_free_memslot(struct kvm_memory_slot *free,
|
||||
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
|
||||
struct kvm_memory_slot *dont)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
|
||||
int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
|
||||
unsigned long npages)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -797,6 +798,19 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
||||
return -EFAULT;
|
||||
return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr);
|
||||
}
|
||||
case KVM_ARM_PREFERRED_TARGET: {
|
||||
int err;
|
||||
struct kvm_vcpu_init init;
|
||||
|
||||
err = kvm_vcpu_preferred_target(&init);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (copy_to_user(argp, &init, sizeof(init)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,98 @@ int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
|
||||
{
|
||||
/*
|
||||
* Compute guest MPIDR. We build a virtual cluster out of the
|
||||
* vcpu_id, but we read the 'U' bit from the underlying
|
||||
* hardware directly.
|
||||
*/
|
||||
vcpu->arch.cp15[c0_MPIDR] = ((read_cpuid_mpidr() & MPIDR_SMP_BITMASK) |
|
||||
((vcpu->vcpu_id >> 2) << MPIDR_LEVEL_BITS) |
|
||||
(vcpu->vcpu_id & 3));
|
||||
}
|
||||
|
||||
/* TRM entries A7:4.3.31 A15:4.3.28 - RO WI */
|
||||
static bool access_actlr(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR];
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TRM entries A7:4.3.56, A15:4.3.60 - R/O. */
|
||||
static bool access_cbar(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return write_to_read_only(vcpu, p);
|
||||
return read_zero(vcpu, p);
|
||||
}
|
||||
|
||||
/* TRM entries A7:4.3.49, A15:4.3.48 - R/O WI */
|
||||
static bool access_l2ctlr(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR];
|
||||
return true;
|
||||
}
|
||||
|
||||
static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
|
||||
{
|
||||
u32 l2ctlr, ncores;
|
||||
|
||||
asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
|
||||
l2ctlr &= ~(3 << 24);
|
||||
ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
|
||||
/* How many cores in the current cluster and the next ones */
|
||||
ncores -= (vcpu->vcpu_id & ~3);
|
||||
/* Cap it to the maximum number of cores in a single cluster */
|
||||
ncores = min(ncores, 3U);
|
||||
l2ctlr |= (ncores & 3) << 24;
|
||||
|
||||
vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
|
||||
}
|
||||
|
||||
static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
|
||||
{
|
||||
u32 actlr;
|
||||
|
||||
/* ACTLR contains SMP bit: make sure you create all cpus first! */
|
||||
asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
|
||||
/* Make the SMP bit consistent with the guest configuration */
|
||||
if (atomic_read(&vcpu->kvm->online_vcpus) > 1)
|
||||
actlr |= 1U << 6;
|
||||
else
|
||||
actlr &= ~(1U << 6);
|
||||
|
||||
vcpu->arch.cp15[c1_ACTLR] = actlr;
|
||||
}
|
||||
|
||||
/*
|
||||
* TRM entries: A7:4.3.50, A15:4.3.49
|
||||
* R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored).
|
||||
*/
|
||||
static bool access_l2ectlr(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
*vcpu_reg(vcpu, p->Rt1) = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See note at ARM ARM B1.14.4 */
|
||||
static bool access_dcsw(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
@@ -153,10 +245,22 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
|
||||
* registers preceding 32-bit ones.
|
||||
*/
|
||||
static const struct coproc_reg cp15_regs[] = {
|
||||
/* MPIDR: we use VMPIDR for guest access. */
|
||||
{ CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
|
||||
NULL, reset_mpidr, c0_MPIDR },
|
||||
|
||||
/* CSSELR: swapped by interrupt.S. */
|
||||
{ CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32,
|
||||
NULL, reset_unknown, c0_CSSELR },
|
||||
|
||||
/* ACTLR: trapped by HCR.TAC bit. */
|
||||
{ CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32,
|
||||
access_actlr, reset_actlr, c1_ACTLR },
|
||||
|
||||
/* CPACR: swapped by interrupt.S. */
|
||||
{ CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
|
||||
NULL, reset_val, c1_CPACR, 0x00000000 },
|
||||
|
||||
/* TTBR0/TTBR1: swapped by interrupt.S. */
|
||||
{ CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
|
||||
{ CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
|
||||
@@ -194,6 +298,13 @@ static const struct coproc_reg cp15_regs[] = {
|
||||
{ CRn( 7), CRm( 6), Op1( 0), Op2( 2), is32, access_dcsw},
|
||||
{ CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw},
|
||||
{ CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw},
|
||||
/*
|
||||
* L2CTLR access (guest wants to know #CPUs).
|
||||
*/
|
||||
{ CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32,
|
||||
access_l2ctlr, reset_l2ctlr, c9_L2CTLR },
|
||||
{ CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr},
|
||||
|
||||
/*
|
||||
* Dummy performance monitor implementation.
|
||||
*/
|
||||
@@ -234,6 +345,9 @@ static const struct coproc_reg cp15_regs[] = {
|
||||
/* CNTKCTL: swapped by interrupt.S. */
|
||||
{ CRn(14), CRm( 1), Op1( 0), Op2( 0), is32,
|
||||
NULL, reset_val, c14_CNTKCTL, 0x00000000 },
|
||||
|
||||
/* The Configuration Base Address Register. */
|
||||
{ CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
|
||||
};
|
||||
|
||||
/* Target specific emulation tables */
|
||||
@@ -241,6 +355,12 @@ static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS];
|
||||
|
||||
void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < table->num; i++)
|
||||
BUG_ON(cmp_reg(&table->table[i-1],
|
||||
&table->table[i]) >= 0);
|
||||
|
||||
target_tables[table->target] = table;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,101 +17,12 @@
|
||||
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/kvm_host.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/kvm_arm.h>
|
||||
#include <asm/kvm_host.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <asm/kvm_coproc.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
|
||||
{
|
||||
/*
|
||||
* Compute guest MPIDR:
|
||||
* (Even if we present only one VCPU to the guest on an SMP
|
||||
* host we don't set the U bit in the MPIDR, or vice versa, as
|
||||
* revealing the underlying hardware properties is likely to
|
||||
* be the best choice).
|
||||
*/
|
||||
vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & ~MPIDR_LEVEL_MASK)
|
||||
| (vcpu->vcpu_id & MPIDR_LEVEL_MASK);
|
||||
}
|
||||
|
||||
#include "coproc.h"
|
||||
|
||||
/* A15 TRM 4.3.28: RO WI */
|
||||
static bool access_actlr(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR];
|
||||
return true;
|
||||
}
|
||||
|
||||
/* A15 TRM 4.3.60: R/O. */
|
||||
static bool access_cbar(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return write_to_read_only(vcpu, p);
|
||||
return read_zero(vcpu, p);
|
||||
}
|
||||
|
||||
/* A15 TRM 4.3.48: R/O WI. */
|
||||
static bool access_l2ctlr(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR];
|
||||
return true;
|
||||
}
|
||||
|
||||
static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
|
||||
{
|
||||
u32 l2ctlr, ncores;
|
||||
|
||||
asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
|
||||
l2ctlr &= ~(3 << 24);
|
||||
ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
|
||||
l2ctlr |= (ncores & 3) << 24;
|
||||
|
||||
vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
|
||||
}
|
||||
|
||||
static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
|
||||
{
|
||||
u32 actlr;
|
||||
|
||||
/* ACTLR contains SMP bit: make sure you create all cpus first! */
|
||||
asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
|
||||
/* Make the SMP bit consistent with the guest configuration */
|
||||
if (atomic_read(&vcpu->kvm->online_vcpus) > 1)
|
||||
actlr |= 1U << 6;
|
||||
else
|
||||
actlr &= ~(1U << 6);
|
||||
|
||||
vcpu->arch.cp15[c1_ACTLR] = actlr;
|
||||
}
|
||||
|
||||
/* A15 TRM 4.3.49: R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored). */
|
||||
static bool access_l2ectlr(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_params *p,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
*vcpu_reg(vcpu, p->Rt1) = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* A15-specific CP15 registers.
|
||||
* CRn denotes the primary register number, but is copied to the CRm in the
|
||||
@@ -121,29 +32,9 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
|
||||
* registers preceding 32-bit ones.
|
||||
*/
|
||||
static const struct coproc_reg a15_regs[] = {
|
||||
/* MPIDR: we use VMPIDR for guest access. */
|
||||
{ CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
|
||||
NULL, reset_mpidr, c0_MPIDR },
|
||||
|
||||
/* SCTLR: swapped by interrupt.S. */
|
||||
{ CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
|
||||
NULL, reset_val, c1_SCTLR, 0x00C50078 },
|
||||
/* ACTLR: trapped by HCR.TAC bit. */
|
||||
{ CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32,
|
||||
access_actlr, reset_actlr, c1_ACTLR },
|
||||
/* CPACR: swapped by interrupt.S. */
|
||||
{ CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
|
||||
NULL, reset_val, c1_CPACR, 0x00000000 },
|
||||
|
||||
/*
|
||||
* L2CTLR access (guest wants to know #CPUs).
|
||||
*/
|
||||
{ CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32,
|
||||
access_l2ctlr, reset_l2ctlr, c9_L2CTLR },
|
||||
{ CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr},
|
||||
|
||||
/* The Configuration Base Address Register. */
|
||||
{ CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
|
||||
};
|
||||
|
||||
static struct kvm_coproc_target_table a15_target_table = {
|
||||
@@ -154,12 +45,6 @@ static struct kvm_coproc_target_table a15_target_table = {
|
||||
|
||||
static int __init coproc_a15_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < ARRAY_SIZE(a15_regs); i++)
|
||||
BUG_ON(cmp_reg(&a15_regs[i-1],
|
||||
&a15_regs[i]) >= 0);
|
||||
|
||||
kvm_register_target_coproc_table(&a15_target_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
54
arch/arm/kvm/coproc_a7.c
Normal file
54
arch/arm/kvm/coproc_a7.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2012 - Virtual Open Systems and Columbia University
|
||||
* Copyright (C) 2013 - ARM Ltd
|
||||
*
|
||||
* Authors: Rusty Russell <rusty@rustcorp.au>
|
||||
* Christoffer Dall <c.dall@virtualopensystems.com>
|
||||
* Jonathan Austin <jonathan.austin@arm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/kvm_host.h>
|
||||
#include <asm/kvm_coproc.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "coproc.h"
|
||||
|
||||
/*
|
||||
* Cortex-A7 specific CP15 registers.
|
||||
* CRn denotes the primary register number, but is copied to the CRm in the
|
||||
* user space API for 64-bit register access in line with the terminology used
|
||||
* in the ARM ARM.
|
||||
* Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
|
||||
* registers preceding 32-bit ones.
|
||||
*/
|
||||
static const struct coproc_reg a7_regs[] = {
|
||||
/* SCTLR: swapped by interrupt.S. */
|
||||
{ CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
|
||||
NULL, reset_val, c1_SCTLR, 0x00C50878 },
|
||||
};
|
||||
|
||||
static struct kvm_coproc_target_table a7_target_table = {
|
||||
.target = KVM_ARM_TARGET_CORTEX_A7,
|
||||
.table = a7_regs,
|
||||
.num = ARRAY_SIZE(a7_regs),
|
||||
};
|
||||
|
||||
static int __init coproc_a7_init(void)
|
||||
{
|
||||
kvm_register_target_coproc_table(&a7_target_table);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(coproc_a7_init);
|
||||
@@ -354,7 +354,7 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
|
||||
*vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
|
||||
|
||||
if (is_pabt) {
|
||||
/* Set DFAR and DFSR */
|
||||
/* Set IFAR and IFSR */
|
||||
vcpu->arch.cp15[c6_IFAR] = addr;
|
||||
is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31);
|
||||
/* Always give debug fault for now - should give guest a clue */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user