Updates for KVM/ARM including cpu=host and Cortex-A7 support
Unified · Split
| @@ -2304,7 +2304,31 @@ Possible features: · 2303 unmodified lines | ||
| 2304 | 2304 | Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). |
| 2305 | 2305 | |
| 2306 | 2306 | |
| 2307 | −4.83 KVM_GET_REG_LIST | |
| 2307 | +4.83 KVM_ARM_PREFERRED_TARGET | |
| 2308 | + | |
| 2309 | +Capability: basic | |
| 2310 | +Architectures: arm, arm64 | |
| 2311 | +Type: vm ioctl | |
| 2312 | +Parameters: struct struct kvm_vcpu_init (out) | |
| 2313 | +Returns: 0 on success; -1 on error | |
| 2314 | +Errors: | |
| 2315 | + ENODEV: no preferred target available for the host | |
| 2316 | + | |
| 2317 | +This queries KVM for preferred CPU target type which can be emulated | |
| 2318 | +by KVM on underlying host. | |
| 2319 | + | |
| 2320 | +The ioctl returns struct kvm_vcpu_init instance containing information | |
| 2321 | +about preferred CPU target type and recommended features for it. The | |
| 2322 | +kvm_vcpu_init->features bitmap returned will have feature bits set if | |
| 2323 | +the preferred target recommends setting these features, but this is | |
| 2324 | +not mandatory. | |
| 2325 | + | |
| 2326 | +The information returned by this ioctl can be used to prepare an instance | |
| 2327 | +of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in | |
| 2328 | +in VCPU matching underlying host. | |
| 2329 | + | |
| 2330 | + | |
| 2331 | +4.84 KVM_GET_REG_LIST | |
| 2308 | 2332 | |
| 2309 | 2333 | Capability: basic |
| 2310 | 2334 | Architectures: arm, arm64 |
| @@ -2323,8 +2347,7 @@ struct kvm_reg_list { · 12 unmodified lines | ||
| 2323 | 2347 | This ioctl returns the guest registers that are supported for the |
| 2324 | 2348 | KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. |
| 2325 | 2349 | |
| 2326 | − | |
| 2327 | −4.84 KVM_ARM_SET_DEVICE_ADDR | |
| 2350 | +4.85 KVM_ARM_SET_DEVICE_ADDR | |
| 2328 | 2351 | |
| 2329 | 2352 | Capability: KVM_CAP_ARM_SET_DEVICE_ADDR |
| 2330 | 2353 | Architectures: arm, arm64 |
| @@ -2362,7 +2385,7 @@ must be called after calling KVM_CREATE_IRQCHIP, but before calling · 31 unmodified lines | ||
| 2362 | 2385 | KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the |
| 2363 | 2386 | base addresses will return -EEXIST. |
| 2364 | 2387 | |
| 2365 | −4.85 KVM_PPC_RTAS_DEFINE_TOKEN | |
| 2388 | +4.86 KVM_PPC_RTAS_DEFINE_TOKEN | |
| 2366 | 2389 | |
| 2367 | 2390 | Capability: KVM_CAP_PPC_RTAS |
| 2368 | 2391 | Architectures: ppc |
| @@ -95,12 +95,12 @@ · 94 unmodified lines | ||
| 95 | 95 | #define TTBCR_IRGN1 (3 << 24) |
| 96 | 96 | #define TTBCR_EPD1 (1 << 23) |
| 97 | 97 | #define TTBCR_A1 (1 << 22) |
| 98 | −#define TTBCR_T1SZ (3 << 16) | |
| 98 | +#define TTBCR_T1SZ (7 << 16) | |
| 99 | 99 | #define TTBCR_SH0 (3 << 12) |
| 100 | 100 | #define TTBCR_ORGN0 (3 << 10) |
| 101 | 101 | #define TTBCR_IRGN0 (3 << 8) |
| 102 | 102 | #define TTBCR_EPD0 (1 << 7) |
| 103 | −#define TTBCR_T0SZ 3 | |
| 103 | +#define TTBCR_T0SZ (7 << 0) | |
| 104 | 104 | #define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0) |
| 105 | 105 | |
| 106 | 106 | /* Hyp System Trap Register */ |
| @@ -39,7 +39,7 @@ · 38 unmodified lines | ||
| 39 | 39 | #define c6_IFAR 17 /* Instruction Fault Address Register */ |
| 40 | 40 | #define c7_PAR 18 /* Physical Address Register */ |
| 41 | 41 | #define c7_PAR_high 19 /* PAR top 32 bits */ |
| 42 | −#define c9_L2CTLR 20 /* Cortex A15 L2 Control Register */ | |
| 42 | +#define c9_L2CTLR 20 /* Cortex A15/A7 L2 Control Register */ | |
| 43 | 43 | #define c10_PRRR 21 /* Primary Region Remap Register */ |
| 44 | 44 | #define c10_NMRR 22 /* Normal Memory Remap Register */ |
| 45 | 45 | #define c12_VBAR 23 /* Vector Base Address Register */ |
| @@ -149,6 +149,7 @@ struct kvm_vcpu_stat { · 148 unmodified lines | ||
| 149 | 149 | struct kvm_vcpu_init; |
| 150 | 150 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, |
| 151 | 151 | const struct kvm_vcpu_init *init); |
| 152 | +int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); | |
| 152 | 153 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); |
| 153 | 154 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); |
| 154 | 155 | struct kvm_one_reg; |
| @@ -63,7 +63,8 @@ struct kvm_regs { · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | /* Supported Processor Types */ |
| 65 | 65 | #define KVM_ARM_TARGET_CORTEX_A15 0 |
| 66 | −#define KVM_ARM_NUM_TARGETS 1 | |
| 66 | +#define KVM_ARM_TARGET_CORTEX_A7 1 | |
| 67 | +#define KVM_ARM_NUM_TARGETS 2 | |
| 67 | 68 | |
| 68 | 69 | /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */ |
| 69 | 70 | #define KVM_ARM_DEVICE_TYPE_SHIFT 0 |
| @@ -19,6 +19,6 @@ kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | obj-y += kvm-arm.o init.o interrupts.o |
| 21 | 21 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o |
| 22 | −obj-y += coproc.o coproc_a15.o mmio.o psci.o perf.o | |
| 22 | +obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o | |
| 23 | 23 | obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o |
| 24 | 24 | obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o |
| @@ -797,6 +797,19 @@ long kvm_arch_vm_ioctl(struct file *filp, · 796 unmodified lines | ||
| 797 | 797 | return -EFAULT; |
| 798 | 798 | return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); |
| 799 | 799 | } |
| 800 | + case KVM_ARM_PREFERRED_TARGET: { | |
| 801 | + int err; | |
| 802 | + struct kvm_vcpu_init init; | |
| 803 | + | |
| 804 | + err = kvm_vcpu_preferred_target(&init); | |
| 805 | + if (err) | |
| 806 | + return err; | |
| 807 | + | |
| 808 | + if (copy_to_user(argp, &init, sizeof(init))) | |
| 809 | + return -EFAULT; | |
| 810 | + | |
| 811 | + return 0; | |
| 812 | + } | |
| 800 | 813 | default: |
| 801 | 814 | return -EINVAL; |
| 802 | 815 | } |
| @@ -71,6 +71,92 @@ int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run) · 70 unmodified lines | ||
| 71 | 71 | return 1; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | +static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | |
| 75 | +{ | |
| 76 | + /* | |
| 77 | + * Compute guest MPIDR. No need to mess around with different clusters | |
| 78 | + * but we read the 'U' bit from the underlying hardware directly. | |
| 79 | + */ | |
| 80 | + vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & MPIDR_SMP_BITMASK) | |
| 81 | + | vcpu->vcpu_id; | |
| 82 | +} | |
| 83 | + | |
| 84 | +/* TRM entries A7:4.3.31 A15:4.3.28 - RO WI */ | |
| 85 | +static bool access_actlr(struct kvm_vcpu *vcpu, | |
| 86 | + const struct coproc_params *p, | |
| 87 | + const struct coproc_reg *r) | |
| 88 | +{ | |
| 89 | + if (p->is_write) | |
| 90 | + return ignore_write(vcpu, p); | |
| 91 | + | |
| 92 | + *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR]; | |
| 93 | + return true; | |
| 94 | +} | |
| 95 | + | |
| 96 | +/* TRM entries A7:4.3.56, A15:4.3.60 - R/O. */ | |
| 97 | +static bool access_cbar(struct kvm_vcpu *vcpu, | |
| 98 | + const struct coproc_params *p, | |
| 99 | + const struct coproc_reg *r) | |
| 100 | +{ | |
| 101 | + if (p->is_write) | |
| 102 | + return write_to_read_only(vcpu, p); | |
| 103 | + return read_zero(vcpu, p); | |
| 104 | +} | |
| 105 | + | |
| 106 | +/* TRM entries A7:4.3.49, A15:4.3.48 - R/O WI */ | |
| 107 | +static bool access_l2ctlr(struct kvm_vcpu *vcpu, | |
| 108 | + const struct coproc_params *p, | |
| 109 | + const struct coproc_reg *r) | |
| 110 | +{ | |
| 111 | + if (p->is_write) | |
| 112 | + return ignore_write(vcpu, p); | |
| 113 | + | |
| 114 | + *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR]; | |
| 115 | + return true; | |
| 116 | +} | |
| 117 | + | |
| 118 | +static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | |
| 119 | +{ | |
| 120 | + u32 l2ctlr, ncores; | |
| 121 | + | |
| 122 | + asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); | |
| 123 | + l2ctlr &= ~(3 << 24); | |
| 124 | + ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1; | |
| 125 | + l2ctlr |= (ncores & 3) << 24; | |
| 126 | + | |
| 127 | + vcpu->arch.cp15[c9_L2CTLR] = l2ctlr; | |
| 128 | +} | |
| 129 | + | |
| 130 | +static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | |
| 131 | +{ | |
| 132 | + u32 actlr; | |
| 133 | + | |
| 134 | + /* ACTLR contains SMP bit: make sure you create all cpus first! */ | |
| 135 | + asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr)); | |
| 136 | + /* Make the SMP bit consistent with the guest configuration */ | |
| 137 | + if (atomic_read(&vcpu->kvm->online_vcpus) > 1) | |
| 138 | + actlr |= 1U << 6; | |
| 139 | + else | |
| 140 | + actlr &= ~(1U << 6); | |
| 141 | + | |
| 142 | + vcpu->arch.cp15[c1_ACTLR] = actlr; | |
| 143 | +} | |
| 144 | + | |
| 145 | +/* | |
| 146 | + * TRM entries: A7:4.3.50, A15:4.3.49 | |
| 147 | + * R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored). | |
| 148 | + */ | |
| 149 | +static bool access_l2ectlr(struct kvm_vcpu *vcpu, | |
| 150 | + const struct coproc_params *p, | |
| 151 | + const struct coproc_reg *r) | |
| 152 | +{ | |
| 153 | + if (p->is_write) | |
| 154 | + return ignore_write(vcpu, p); | |
| 155 | + | |
| 156 | + *vcpu_reg(vcpu, p->Rt1) = 0; | |
| 157 | + return true; | |
| 158 | +} | |
| 159 | + | |
| 74 | 160 | /* See note at ARM ARM B1.14.4 */ |
| 75 | 161 | static bool access_dcsw(struct kvm_vcpu *vcpu, |
| 76 | 162 | const struct coproc_params *p, |
| @@ -153,10 +239,22 @@ static bool pm_fake(struct kvm_vcpu *vcpu, · 76 unmodified lines | ||
| 153 | 239 | * registers preceding 32-bit ones. |
| 154 | 240 | */ |
| 155 | 241 | static const struct coproc_reg cp15_regs[] = { |
| 242 | + /* MPIDR: we use VMPIDR for guest access. */ | |
| 243 | + { CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32, | |
| 244 | + NULL, reset_mpidr, c0_MPIDR }, | |
| 245 | + | |
| 156 | 246 | /* CSSELR: swapped by interrupt.S. */ |
| 157 | 247 | { CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32, |
| 158 | 248 | NULL, reset_unknown, c0_CSSELR }, |
| 159 | 249 | |
| 250 | + /* ACTLR: trapped by HCR.TAC bit. */ | |
| 251 | + { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32, | |
| 252 | + access_actlr, reset_actlr, c1_ACTLR }, | |
| 253 | + | |
| 254 | + /* CPACR: swapped by interrupt.S. */ | |
| 255 | + { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32, | |
| 256 | + NULL, reset_val, c1_CPACR, 0x00000000 }, | |
| 257 | + | |
| 160 | 258 | /* TTBR0/TTBR1: swapped by interrupt.S. */ |
| 161 | 259 | { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, |
| 162 | 260 | { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, |
| @@ -194,6 +292,13 @@ static const struct coproc_reg cp15_regs[] = { · 31 unmodified lines | ||
| 194 | 292 | { CRn( 7), CRm( 6), Op1( 0), Op2( 2), is32, access_dcsw}, |
| 195 | 293 | { CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw}, |
| 196 | 294 | { CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw}, |
| 295 | + /* | |
| 296 | + * L2CTLR access (guest wants to know #CPUs). | |
| 297 | + */ | |
| 298 | + { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32, | |
| 299 | + access_l2ctlr, reset_l2ctlr, c9_L2CTLR }, | |
| 300 | + { CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr}, | |
| 301 | + | |
| 197 | 302 | /* |
| 198 | 303 | * Dummy performance monitor implementation. |
| 199 | 304 | */ |
| @@ -234,6 +339,9 @@ static const struct coproc_reg cp15_regs[] = { · 34 unmodified lines | ||
| 234 | 339 | /* CNTKCTL: swapped by interrupt.S. */ |
| 235 | 340 | { CRn(14), CRm( 1), Op1( 0), Op2( 0), is32, |
| 236 | 341 | NULL, reset_val, c14_CNTKCTL, 0x00000000 }, |
| 342 | + | |
| 343 | + /* The Configuration Base Address Register. */ | |
| 344 | + { CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar}, | |
| 237 | 345 | }; |
| 238 | 346 | |
| 239 | 347 | /* Target specific emulation tables */ |
| @@ -241,6 +349,12 @@ static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS]; · 1 unmodified line | ||
| 241 | 349 | |
| 242 | 350 | void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table) |
| 243 | 351 | { |
| 352 | + unsigned int i; | |
| 353 | + | |
| 354 | + for (i = 1; i < table->num; i++) | |
| 355 | + BUG_ON(cmp_reg(&table->table[i-1], | |
| 356 | + &table->table[i]) >= 0); | |
| 357 | + | |
| 244 | 358 | target_tables[table->target] = table; |
| 245 | 359 | } |
| 246 | 360 | |
| @@ -17,101 +17,12 @@ · 16 unmodified lines | ||
| 17 | 17 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 18 | 18 | */ |
| 19 | 19 | #include <linux/kvm_host.h> |
| 20 | −#include <asm/cputype.h> | |
| 21 | −#include <asm/kvm_arm.h> | |
| 22 | −#include <asm/kvm_host.h> | |
| 23 | −#include <asm/kvm_emulate.h> | |
| 24 | 20 | #include <asm/kvm_coproc.h> |
| 21 | +#include <asm/kvm_emulate.h> | |
| 25 | 22 | #include <linux/init.h> |
| 26 | 23 | |
| 27 | −static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | |
| 28 | −{ | |
| 29 | − /* | |
| 30 | − * Compute guest MPIDR: | |
| 31 | − * (Even if we present only one VCPU to the guest on an SMP | |
| 32 | − * host we don't set the U bit in the MPIDR, or vice versa, as | |
| 33 | − * revealing the underlying hardware properties is likely to | |
| 34 | − * be the best choice). | |
| 35 | − */ | |
| 36 | − vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & ~MPIDR_LEVEL_MASK) | |
| 37 | − | (vcpu->vcpu_id & MPIDR_LEVEL_MASK); | |
| 38 | −} | |
| 39 | − | |
| 40 | 24 | #include "coproc.h" |
| 41 | 25 | |
| 42 | −/* A15 TRM 4.3.28: RO WI */ | |
| 43 | −static bool access_actlr(struct kvm_vcpu *vcpu, | |
| 44 | − const struct coproc_params *p, | |
| 45 | − const struct coproc_reg *r) | |
| 46 | −{ | |
| 47 | − if (p->is_write) | |
| 48 | − return ignore_write(vcpu, p); | |
| 49 | − | |
| 50 | − *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR]; | |
| 51 | − return true; | |
| 52 | −} | |
| 53 | − | |
| 54 | −/* A15 TRM 4.3.60: R/O. */ | |
| 55 | −static bool access_cbar(struct kvm_vcpu *vcpu, | |
| 56 | − const struct coproc_params *p, | |
| 57 | − const struct coproc_reg *r) | |
| 58 | −{ | |
| 59 | − if (p->is_write) | |
| 60 | − return write_to_read_only(vcpu, p); | |
| 61 | − return read_zero(vcpu, p); | |
| 62 | −} | |
| 63 | − | |
| 64 | −/* A15 TRM 4.3.48: R/O WI. */ | |
| 65 | −static bool access_l2ctlr(struct kvm_vcpu *vcpu, | |
| 66 | − const struct coproc_params *p, | |
| 67 | − const struct coproc_reg *r) | |
| 68 | −{ | |
| 69 | − if (p->is_write) | |
| 70 | − return ignore_write(vcpu, p); | |
| 71 | − | |
| 72 | − *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR]; | |
| 73 | − return true; | |
| 74 | −} | |
| 75 | − | |
| 76 | −static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | |
| 77 | −{ | |
| 78 | − u32 l2ctlr, ncores; | |
| 79 | − | |
| 80 | − asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); | |
| 81 | − l2ctlr &= ~(3 << 24); | |
| 82 | − ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1; | |
| 83 | − l2ctlr |= (ncores & 3) << 24; | |
| 84 | − | |
| 85 | − vcpu->arch.cp15[c9_L2CTLR] = l2ctlr; | |
| 86 | −} | |
| 87 | − | |
| 88 | −static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | |
| 89 | −{ | |
| 90 | − u32 actlr; | |
| 91 | − | |
| 92 | − /* ACTLR contains SMP bit: make sure you create all cpus first! */ | |
| 93 | − asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr)); | |
| 94 | − /* Make the SMP bit consistent with the guest configuration */ | |
| 95 | − if (atomic_read(&vcpu->kvm->online_vcpus) > 1) | |
| 96 | − actlr |= 1U << 6; | |
| 97 | − else | |
| 98 | − actlr &= ~(1U << 6); | |
| 99 | − | |
| 100 | − vcpu->arch.cp15[c1_ACTLR] = actlr; | |
| 101 | −} | |
| 102 | − | |
| 103 | −/* A15 TRM 4.3.49: R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored). */ | |
| 104 | −static bool access_l2ectlr(struct kvm_vcpu *vcpu, | |
| 105 | − const struct coproc_params *p, | |
| 106 | − const struct coproc_reg *r) | |
| 107 | −{ | |
| 108 | − if (p->is_write) | |
| 109 | − return ignore_write(vcpu, p); | |
| 110 | − | |
| 111 | − *vcpu_reg(vcpu, p->Rt1) = 0; | |
| 112 | − return true; | |
| 113 | −} | |
| 114 | − | |
| 115 | 26 | /* |
| 116 | 27 | * A15-specific CP15 registers. |
| 117 | 28 | * 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, · 3 unmodified lines | ||
| 121 | 32 | * registers preceding 32-bit ones. |
| 122 | 33 | */ |
| 123 | 34 | static const struct coproc_reg a15_regs[] = { |
| 124 | − /* MPIDR: we use VMPIDR for guest access. */ | |
| 125 | − { CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32, | |
| 126 | − NULL, reset_mpidr, c0_MPIDR }, | |
| 127 | − | |
| 128 | 35 | /* SCTLR: swapped by interrupt.S. */ |
| 129 | 36 | { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, |
| 130 | 37 | NULL, reset_val, c1_SCTLR, 0x00C50078 }, |
| 131 | − /* ACTLR: trapped by HCR.TAC bit. */ | |
| 132 | − { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32, | |
| 133 | − access_actlr, reset_actlr, c1_ACTLR }, | |
| 134 | − /* CPACR: swapped by interrupt.S. */ | |
| 135 | − { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32, | |
| 136 | − NULL, reset_val, c1_CPACR, 0x00000000 }, | |
| 137 | − | |
| 138 | − /* | |
| 139 | − * L2CTLR access (guest wants to know #CPUs). | |
| 140 | − */ | |
| 141 | − { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32, | |
| 142 | − access_l2ctlr, reset_l2ctlr, c9_L2CTLR }, | |
| 143 | − { CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr}, | |
| 144 | − | |
| 145 | − /* The Configuration Base Address Register. */ | |
| 146 | − { CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar}, | |
| 147 | 38 | }; |
| 148 | 39 | |
| 149 | 40 | static struct kvm_coproc_target_table a15_target_table = { |
| @@ -154,12 +45,6 @@ static struct kvm_coproc_target_table a15_target_table = { · 4 unmodified lines | ||
| 154 | 45 | |
| 155 | 46 | static int __init coproc_a15_init(void) |
| 156 | 47 | { |
| 157 | − unsigned int i; | |
| 158 | − | |
| 159 | − for (i = 1; i < ARRAY_SIZE(a15_regs); i++) | |
| 160 | − BUG_ON(cmp_reg(&a15_regs[i-1], | |
| 161 | − &a15_regs[i]) >= 0); | |
| 162 | − | |
| 163 | 48 | kvm_register_target_coproc_table(&a15_target_table); |
| 164 | 49 | return 0; |
| 165 | 50 | } |
| @@ -0,0 +1,54 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2012 - Virtual Open Systems and Columbia University | |
| 3 | + * Copyright (C) 2013 - ARM Ltd | |
| 4 | + * | |
| 5 | + * Authors: Rusty Russell <rusty@rustcorp.au> | |
| 6 | + * Christoffer Dall <c.dall@virtualopensystems.com> | |
| 7 | + * Jonathan Austin <jonathan.austin@arm.com> | |
| 8 | + * | |
| 9 | + * This program is free software; you can redistribute it and/or modify | |
| 10 | + * it under the terms of the GNU General Public License, version 2, as | |
| 11 | + * published by the Free Software Foundation. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + * | |
| 18 | + * You should have received a copy of the GNU General Public License | |
| 19 | + * along with this program; if not, write to the Free Software | |
| 20 | + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 21 | + */ | |
| 22 | +#include <linux/kvm_host.h> | |
| 23 | +#include <asm/kvm_coproc.h> | |
| 24 | +#include <asm/kvm_emulate.h> | |
| 25 | +#include <linux/init.h> | |
| 26 | + | |
| 27 | +#include "coproc.h" | |
| 28 | + | |
| 29 | +/* | |
| 30 | + * Cortex-A7 specific CP15 registers. | |
| 31 | + * CRn denotes the primary register number, but is copied to the CRm in the | |
| 32 | + * user space API for 64-bit register access in line with the terminology used | |
| 33 | + * in the ARM ARM. | |
| 34 | + * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit | |
| 35 | + * registers preceding 32-bit ones. | |
| 36 | + */ | |
| 37 | +static const struct coproc_reg a7_regs[] = { | |
| 38 | + /* SCTLR: swapped by interrupt.S. */ | |
| 39 | + { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, | |
| 40 | + NULL, reset_val, c1_SCTLR, 0x00C50878 }, | |
| 41 | +}; | |
| 42 | + | |
| 43 | +static struct kvm_coproc_target_table a7_target_table = { | |
| 44 | + .target = KVM_ARM_TARGET_CORTEX_A7, | |
| 45 | + .table = a7_regs, | |
| 46 | + .num = ARRAY_SIZE(a7_regs), | |
| 47 | +}; | |
| 48 | + | |
| 49 | +static int __init coproc_a7_init(void) | |
| 50 | +{ | |
| 51 | + kvm_register_target_coproc_table(&a7_target_table); | |
| 52 | + return 0; | |
| 53 | +} | |
| 54 | +late_initcall(coproc_a7_init); | |
| @@ -354,7 +354,7 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) · 353 unmodified lines | ||
| 354 | 354 | *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; |
| 355 | 355 | |
| 356 | 356 | if (is_pabt) { |
| 357 | − /* Set DFAR and DFSR */ | |
| 357 | + /* Set IFAR and IFSR */ | |
| 358 | 358 | vcpu->arch.cp15[c6_IFAR] = addr; |
| 359 | 359 | is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31); |
| 360 | 360 | /* Always give debug fault for now - should give guest a clue */ |
| @@ -190,6 +190,8 @@ int __attribute_const__ kvm_target_cpu(void) · 189 unmodified lines | ||
| 190 | 190 | return -EINVAL; |
| 191 | 191 | |
| 192 | 192 | switch (part_number) { |
| 193 | + case ARM_CPU_PART_CORTEX_A7: | |
| 194 | + return KVM_ARM_TARGET_CORTEX_A7; | |
| 193 | 195 | case ARM_CPU_PART_CORTEX_A15: |
| 194 | 196 | return KVM_ARM_TARGET_CORTEX_A15; |
| 195 | 197 | default: |
| @@ -202,7 +204,7 @@ int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, · 6 unmodified lines | ||
| 202 | 204 | { |
| 203 | 205 | unsigned int i; |
| 204 | 206 | |
| 205 | − /* We can only do a cortex A15 for now. */ | |
| 207 | + /* We can only cope with guest==host and only on A15/A7 (for now). */ | |
| 206 | 208 | if (init->target != kvm_target_cpu()) |
| 207 | 209 | return -EINVAL; |
| 208 | 210 | |
| @@ -222,6 +224,26 @@ int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, · 13 unmodified lines | ||
| 222 | 224 | return kvm_reset_vcpu(vcpu); |
| 223 | 225 | } |
| 224 | 226 | |
| 227 | +int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) | |
| 228 | +{ | |
| 229 | + int target = kvm_target_cpu(); | |
| 230 | + | |
| 231 | + if (target < 0) | |
| 232 | + return -ENODEV; | |
| 233 | + | |
| 234 | + memset(init, 0, sizeof(*init)); | |
| 235 | + | |
| 236 | + /* | |
| 237 | + * For now, we don't return any features. | |
| 238 | + * In future, we might use features to return target | |
| 239 | + * specific features available for the preferred | |
| 240 | + * target type. | |
| 241 | + */ | |
| 242 | + init->target = (__u32)target; | |
| 243 | + | |
| 244 | + return 0; | |
| 245 | +} | |
| 246 | + | |
| 225 | 247 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) |
| 226 | 248 | { |
| 227 | 249 | return -EINVAL; |
| @@ -30,16 +30,16 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <kvm/arm_arch_timer.h> |
| 31 | 31 | |
| 32 | 32 | /****************************************************************************** |
| 33 | − * Cortex-A15 Reset Values | |
| 33 | + * Cortex-A15 and Cortex-A7 Reset Values | |
| 34 | 34 | */ |
| 35 | 35 | |
| 36 | −static const int a15_max_cpu_idx = 3; | |
| 36 | +static const int cortexa_max_cpu_idx = 3; | |
| 37 | 37 | |
| 38 | −static struct kvm_regs a15_regs_reset = { | |
| 38 | +static struct kvm_regs cortexa_regs_reset = { | |
| 39 | 39 | .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT, |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | −static const struct kvm_irq_level a15_vtimer_irq = { | |
| 42 | +static const struct kvm_irq_level cortexa_vtimer_irq = { | |
| 43 | 43 | { .irq = 27 }, |
| 44 | 44 | .level = 1, |
| 45 | 45 | }; |
| @@ -62,12 +62,13 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) · 16 unmodified lines | ||
| 62 | 62 | const struct kvm_irq_level *cpu_vtimer_irq; |
| 63 | 63 | |
| 64 | 64 | switch (vcpu->arch.target) { |
| 65 | + case KVM_ARM_TARGET_CORTEX_A7: | |
| 65 | 66 | case KVM_ARM_TARGET_CORTEX_A15: |
| 66 | − if (vcpu->vcpu_id > a15_max_cpu_idx) | |
| 67 | + if (vcpu->vcpu_id > cortexa_max_cpu_idx) | |
| 67 | 68 | return -EINVAL; |
| 68 | − cpu_reset = &a15_regs_reset; | |
| 69 | + cpu_reset = &cortexa_regs_reset; | |
| 69 | 70 | vcpu->arch.midr = read_cpuid_id(); |
| 70 | − cpu_vtimer_irq = &a15_vtimer_irq; | |
| 71 | + cpu_vtimer_irq = &cortexa_vtimer_irq; | |
| 71 | 72 | break; |
| 72 | 73 | default: |
| 73 | 74 | return -ENODEV; |
| @@ -146,6 +146,7 @@ struct kvm_vcpu_stat { · 145 unmodified lines | ||
| 146 | 146 | struct kvm_vcpu_init; |
| 147 | 147 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, |
| 148 | 148 | const struct kvm_vcpu_init *init); |
| 149 | +int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); | |
| 149 | 150 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); |
| 150 | 151 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); |
| 151 | 152 | struct kvm_one_reg; |
| @@ -248,6 +248,26 @@ int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, · 247 unmodified lines | ||
| 248 | 248 | return kvm_reset_vcpu(vcpu); |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | +int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) | |
| 252 | +{ | |
| 253 | + int target = kvm_target_cpu(); | |
| 254 | + | |
| 255 | + if (target < 0) | |
| 256 | + return -ENODEV; | |
| 257 | + | |
| 258 | + memset(init, 0, sizeof(*init)); | |
| 259 | + | |
| 260 | + /* | |
| 261 | + * For now, we don't return any features. | |
| 262 | + * In future, we might use features to return target | |
| 263 | + * specific features available for the preferred | |
| 264 | + * target type. | |
| 265 | + */ | |
| 266 | + init->target = (__u32)target; | |
| 267 | + | |
| 268 | + return 0; | |
| 269 | +} | |
| 270 | + | |
| 251 | 271 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) |
| 252 | 272 | { |
| 253 | 273 | return -EINVAL; |
| @@ -1012,6 +1012,7 @@ struct kvm_s390_ucas_mapping { · 1011 unmodified lines | ||
| 1012 | 1012 | /* VM is being stopped by host */ |
| 1013 | 1013 | #define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad) |
| 1014 | 1014 | #define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init) |
| 1015 | +#define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init) | |
| 1015 | 1016 | #define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list) |
| 1016 | 1017 | |
| 1017 | 1018 | #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) |