Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c9dc9500
Commit
c9dc9500
authored
Jul 28, 2020
by
Marc Zyngier
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'kvm-arm64/target-table-no-more' into kvmarm-master/next-WIP
Signed-off-by:
Marc Zyngier
<
maz@kernel.org
>
parents
fc279329
750ed566
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
56 additions
and
227 deletions
+56
-227
arch/arm64/include/asm/kvm_coproc.h
arch/arm64/include/asm/kvm_coproc.h
+0
-8
arch/arm64/kvm/Makefile
arch/arm64/kvm/Makefile
+1
-1
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/sys_regs.c
+55
-122
arch/arm64/kvm/sys_regs_generic_v8.c
arch/arm64/kvm/sys_regs_generic_v8.c
+0
-96
No files found.
arch/arm64/include/asm/kvm_coproc.h
View file @
c9dc9500
...
...
@@ -19,14 +19,6 @@ struct kvm_sys_reg_table {
size_t
num
;
};
struct
kvm_sys_reg_target_table
{
struct
kvm_sys_reg_table
table64
;
struct
kvm_sys_reg_table
table32
;
};
void
kvm_register_target_sys_reg_table
(
unsigned
int
target
,
struct
kvm_sys_reg_target_table
*
table
);
int
kvm_handle_cp14_load_store
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
);
int
kvm_handle_cp14_32
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
);
int
kvm_handle_cp14_64
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
);
...
...
arch/arm64/kvm/Makefile
View file @
c9dc9500
...
...
@@ -14,7 +14,7 @@ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
$(KVM)
/vfio.o
$(KVM)
/irqchip.o
\
arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o
\
inject_fault.o regmap.o va_layout.o hyp.o handle_exit.o
\
guest.o debug.o reset.o sys_regs.o
sys_regs_generic_v8.o
\
guest.o debug.o reset.o sys_regs.o
\
vgic-sys-reg-v3.o fpsimd.o pmu.o
\
aarch32.o arch_timer.o
\
vgic/vgic.o vgic/vgic-init.o
\
...
...
arch/arm64/kvm/sys_regs.c
View file @
c9dc9500
...
...
@@ -244,6 +244,25 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
return
true
;
}
static
bool
access_actlr
(
struct
kvm_vcpu
*
vcpu
,
struct
sys_reg_params
*
p
,
const
struct
sys_reg_desc
*
r
)
{
if
(
p
->
is_write
)
return
ignore_write
(
vcpu
,
p
);
p
->
regval
=
vcpu_read_sys_reg
(
vcpu
,
ACTLR_EL1
);
if
(
p
->
is_aarch32
)
{
if
(
r
->
Op2
&
2
)
p
->
regval
=
upper_32_bits
(
p
->
regval
);
else
p
->
regval
=
lower_32_bits
(
p
->
regval
);
}
return
true
;
}
/*
* Trap handler for the GICv3 SGI generation system register.
* Forward the request to the VGIC emulation.
...
...
@@ -617,6 +636,12 @@ static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
vcpu_write_sys_reg
(
vcpu
,
amair
,
AMAIR_EL1
);
}
static
void
reset_actlr
(
struct
kvm_vcpu
*
vcpu
,
const
struct
sys_reg_desc
*
r
)
{
u64
actlr
=
read_sysreg
(
actlr_el1
);
vcpu_write_sys_reg
(
vcpu
,
actlr
,
ACTLR_EL1
);
}
static
void
reset_mpidr
(
struct
kvm_vcpu
*
vcpu
,
const
struct
sys_reg_desc
*
r
)
{
u64
mpidr
;
...
...
@@ -1520,6 +1545,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_UNALLOCATED
(
7
,
7
),
{
SYS_DESC
(
SYS_SCTLR_EL1
),
access_vm_reg
,
reset_val
,
SCTLR_EL1
,
0x00C50078
},
{
SYS_DESC
(
SYS_ACTLR_EL1
),
access_actlr
,
reset_actlr
,
ACTLR_EL1
},
{
SYS_DESC
(
SYS_CPACR_EL1
),
NULL
,
reset_val
,
CPACR_EL1
,
0
},
{
SYS_DESC
(
SYS_ZCR_EL1
),
NULL
,
reset_val
,
ZCR_EL1
,
0
,
.
visibility
=
sve_visibility
},
{
SYS_DESC
(
SYS_TTBR0_EL1
),
access_vm_reg
,
reset_unknown
,
TTBR0_EL1
},
...
...
@@ -1959,6 +1985,8 @@ static const struct sys_reg_desc cp14_64_regs[] = {
static
const
struct
sys_reg_desc
cp15_regs
[]
=
{
{
Op1
(
0
),
CRn
(
0
),
CRm
(
0
),
Op2
(
1
),
access_ctr
},
{
Op1
(
0
),
CRn
(
1
),
CRm
(
0
),
Op2
(
0
),
access_vm_reg
,
NULL
,
c1_SCTLR
},
{
Op1
(
0
),
CRn
(
1
),
CRm
(
0
),
Op2
(
1
),
access_actlr
},
{
Op1
(
0
),
CRn
(
1
),
CRm
(
0
),
Op2
(
3
),
access_actlr
},
{
Op1
(
0
),
CRn
(
2
),
CRm
(
0
),
Op2
(
0
),
access_vm_reg
,
NULL
,
c2_TTBR0
},
{
Op1
(
0
),
CRn
(
2
),
CRm
(
0
),
Op2
(
1
),
access_vm_reg
,
NULL
,
c2_TTBR1
},
{
Op1
(
0
),
CRn
(
2
),
CRm
(
0
),
Op2
(
2
),
access_vm_reg
,
NULL
,
c2_TTBCR
},
...
...
@@ -2111,36 +2139,6 @@ static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
return
0
;
}
/* Target specific emulation tables */
static
struct
kvm_sys_reg_target_table
*
target_tables
[
KVM_ARM_NUM_TARGETS
];
void
kvm_register_target_sys_reg_table
(
unsigned
int
target
,
struct
kvm_sys_reg_target_table
*
table
)
{
if
(
check_sysreg_table
(
table
->
table64
.
table
,
table
->
table64
.
num
,
false
)
||
check_sysreg_table
(
table
->
table32
.
table
,
table
->
table32
.
num
,
true
))
return
;
target_tables
[
target
]
=
table
;
}
/* Get specific register table for this target. */
static
const
struct
sys_reg_desc
*
get_target_table
(
unsigned
target
,
bool
mode_is_64
,
size_t
*
num
)
{
struct
kvm_sys_reg_target_table
*
table
;
table
=
target_tables
[
target
];
if
(
mode_is_64
)
{
*
num
=
table
->
table64
.
num
;
return
table
->
table64
.
table
;
}
else
{
*
num
=
table
->
table32
.
num
;
return
table
->
table32
.
table
;
}
}
static
int
match_sys_reg
(
const
void
*
key
,
const
void
*
elt
)
{
const
unsigned
long
pval
=
(
unsigned
long
)
key
;
...
...
@@ -2251,9 +2249,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
*/
static
int
kvm_handle_cp_64
(
struct
kvm_vcpu
*
vcpu
,
const
struct
sys_reg_desc
*
global
,
size_t
nr_global
,
const
struct
sys_reg_desc
*
target_specific
,
size_t
nr_specific
)
size_t
nr_global
)
{
struct
sys_reg_params
params
;
u32
hsr
=
kvm_vcpu_get_hsr
(
vcpu
);
...
...
@@ -2280,14 +2276,11 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
}
/*
* Try to emulate the coprocessor access using the target
* specific table first, and using the global table afterwards.
* If either of the tables contains a handler, handle the
* If the table contains a handler, handle the
* potential register operation in the case of a read and return
* with success.
*/
if
(
!
emulate_cp
(
vcpu
,
&
params
,
target_specific
,
nr_specific
)
||
!
emulate_cp
(
vcpu
,
&
params
,
global
,
nr_global
))
{
if
(
!
emulate_cp
(
vcpu
,
&
params
,
global
,
nr_global
))
{
/* Split up the value between registers for the read side */
if
(
!
params
.
is_write
)
{
vcpu_set_reg
(
vcpu
,
Rt
,
lower_32_bits
(
params
.
regval
));
...
...
@@ -2308,9 +2301,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
*/
static
int
kvm_handle_cp_32
(
struct
kvm_vcpu
*
vcpu
,
const
struct
sys_reg_desc
*
global
,
size_t
nr_global
,
const
struct
sys_reg_desc
*
target_specific
,
size_t
nr_specific
)
size_t
nr_global
)
{
struct
sys_reg_params
params
;
u32
hsr
=
kvm_vcpu_get_hsr
(
vcpu
);
...
...
@@ -2326,8 +2317,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
params
.
Op1
=
(
hsr
>>
14
)
&
0x7
;
params
.
Op2
=
(
hsr
>>
17
)
&
0x7
;
if
(
!
emulate_cp
(
vcpu
,
&
params
,
target_specific
,
nr_specific
)
||
!
emulate_cp
(
vcpu
,
&
params
,
global
,
nr_global
))
{
if
(
!
emulate_cp
(
vcpu
,
&
params
,
global
,
nr_global
))
{
if
(
!
params
.
is_write
)
vcpu_set_reg
(
vcpu
,
Rt
,
params
.
regval
);
return
1
;
...
...
@@ -2339,38 +2329,22 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
int
kvm_handle_cp15_64
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
)
{
const
struct
sys_reg_desc
*
target_specific
;
size_t
num
;
target_specific
=
get_target_table
(
vcpu
->
arch
.
target
,
false
,
&
num
);
return
kvm_handle_cp_64
(
vcpu
,
cp15_64_regs
,
ARRAY_SIZE
(
cp15_64_regs
),
target_specific
,
num
);
return
kvm_handle_cp_64
(
vcpu
,
cp15_64_regs
,
ARRAY_SIZE
(
cp15_64_regs
));
}
int
kvm_handle_cp15_32
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
)
{
const
struct
sys_reg_desc
*
target_specific
;
size_t
num
;
target_specific
=
get_target_table
(
vcpu
->
arch
.
target
,
false
,
&
num
);
return
kvm_handle_cp_32
(
vcpu
,
cp15_regs
,
ARRAY_SIZE
(
cp15_regs
),
target_specific
,
num
);
return
kvm_handle_cp_32
(
vcpu
,
cp15_regs
,
ARRAY_SIZE
(
cp15_regs
));
}
int
kvm_handle_cp14_64
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
)
{
return
kvm_handle_cp_64
(
vcpu
,
cp14_64_regs
,
ARRAY_SIZE
(
cp14_64_regs
),
NULL
,
0
);
return
kvm_handle_cp_64
(
vcpu
,
cp14_64_regs
,
ARRAY_SIZE
(
cp14_64_regs
));
}
int
kvm_handle_cp14_32
(
struct
kvm_vcpu
*
vcpu
,
struct
kvm_run
*
run
)
{
return
kvm_handle_cp_32
(
vcpu
,
cp14_regs
,
ARRAY_SIZE
(
cp14_regs
),
NULL
,
0
);
return
kvm_handle_cp_32
(
vcpu
,
cp14_regs
,
ARRAY_SIZE
(
cp14_regs
));
}
static
bool
is_imp_def_sys_reg
(
struct
sys_reg_params
*
params
)
...
...
@@ -2382,15 +2356,9 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params)
static
int
emulate_sys_reg
(
struct
kvm_vcpu
*
vcpu
,
struct
sys_reg_params
*
params
)
{
size_t
num
;
const
struct
sys_reg_desc
*
table
,
*
r
;
table
=
get_target_table
(
vcpu
->
arch
.
target
,
true
,
&
num
);
const
struct
sys_reg_desc
*
r
;
/* Search target-specific then generic table. */
r
=
find_reg
(
params
,
table
,
num
);
if
(
!
r
)
r
=
find_reg
(
params
,
sys_reg_descs
,
ARRAY_SIZE
(
sys_reg_descs
));
r
=
find_reg
(
params
,
sys_reg_descs
,
ARRAY_SIZE
(
sys_reg_descs
));
if
(
likely
(
r
))
{
perform_access
(
vcpu
,
params
,
r
);
...
...
@@ -2405,14 +2373,20 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
return
1
;
}
static
void
reset_sys_reg_descs
(
struct
kvm_vcpu
*
vcpu
,
const
struct
sys_reg_desc
*
table
,
size_t
num
)
/**
* kvm_reset_sys_regs - sets system registers to reset value
* @vcpu: The VCPU pointer
*
* This function finds the right table above and sets the registers on the
* virtual CPU struct to their architecturally defined reset values.
*/
void
kvm_reset_sys_regs
(
struct
kvm_vcpu
*
vcpu
)
{
unsigned
long
i
;
for
(
i
=
0
;
i
<
num
;
i
++
)
if
(
table
[
i
].
reset
)
table
[
i
].
reset
(
vcpu
,
&
table
[
i
]);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sys_reg_descs
)
;
i
++
)
if
(
sys_reg_descs
[
i
].
reset
)
sys_reg_descs
[
i
].
reset
(
vcpu
,
&
sys_reg_descs
[
i
]);
}
/**
...
...
@@ -2494,8 +2468,7 @@ const struct sys_reg_desc *find_reg_by_id(u64 id,
static
const
struct
sys_reg_desc
*
index_to_sys_reg_desc
(
struct
kvm_vcpu
*
vcpu
,
u64
id
)
{
size_t
num
;
const
struct
sys_reg_desc
*
table
,
*
r
;
const
struct
sys_reg_desc
*
r
;
struct
sys_reg_params
params
;
/* We only do sys_reg for now. */
...
...
@@ -2505,10 +2478,7 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
if
(
!
index_to_params
(
id
,
&
params
))
return
NULL
;
table
=
get_target_table
(
vcpu
->
arch
.
target
,
true
,
&
num
);
r
=
find_reg
(
&
params
,
table
,
num
);
if
(
!
r
)
r
=
find_reg
(
&
params
,
sys_reg_descs
,
ARRAY_SIZE
(
sys_reg_descs
));
r
=
find_reg
(
&
params
,
sys_reg_descs
,
ARRAY_SIZE
(
sys_reg_descs
));
/* Not saved in the sys_reg array and not otherwise accessible? */
if
(
r
&&
!
(
r
->
reg
||
r
->
get_user
))
...
...
@@ -2808,35 +2778,17 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
/* Assumed ordered tables, see kvm_sys_reg_table_init. */
static
int
walk_sys_regs
(
struct
kvm_vcpu
*
vcpu
,
u64
__user
*
uind
)
{
const
struct
sys_reg_desc
*
i
1
,
*
i2
,
*
end1
,
*
end2
;
const
struct
sys_reg_desc
*
i
2
,
*
end2
;
unsigned
int
total
=
0
;
size_t
num
;
int
err
;
/* We check for duplicates here, to allow arch-specific overrides. */
i1
=
get_target_table
(
vcpu
->
arch
.
target
,
true
,
&
num
);
end1
=
i1
+
num
;
i2
=
sys_reg_descs
;
end2
=
sys_reg_descs
+
ARRAY_SIZE
(
sys_reg_descs
);
BUG_ON
(
i1
==
end1
||
i2
==
end2
);
/* Walk carefully, as both tables may refer to the same register. */
while
(
i1
||
i2
)
{
int
cmp
=
cmp_sys_reg
(
i1
,
i2
);
/* target-specific overrides generic entry. */
if
(
cmp
<=
0
)
err
=
walk_one_sys_reg
(
vcpu
,
i1
,
&
uind
,
&
total
);
else
err
=
walk_one_sys_reg
(
vcpu
,
i2
,
&
uind
,
&
total
);
while
(
i2
!=
end2
)
{
err
=
walk_one_sys_reg
(
vcpu
,
i2
++
,
&
uind
,
&
total
);
if
(
err
)
return
err
;
if
(
cmp
<=
0
&&
++
i1
==
end1
)
i1
=
NULL
;
if
(
cmp
>=
0
&&
++
i2
==
end2
)
i2
=
NULL
;
}
return
total
;
}
...
...
@@ -2903,22 +2855,3 @@ void kvm_sys_reg_table_init(void)
/* Clear all higher bits. */
cache_levels
&=
(
1
<<
(
i
*
3
))
-
1
;
}
/**
* kvm_reset_sys_regs - sets system registers to reset value
* @vcpu: The VCPU pointer
*
* This function finds the right table above and sets the registers on the
* virtual CPU struct to their architecturally defined reset values.
*/
void
kvm_reset_sys_regs
(
struct
kvm_vcpu
*
vcpu
)
{
size_t
num
;
const
struct
sys_reg_desc
*
table
;
/* Generic chip reset first (so target could override). */
reset_sys_reg_descs
(
vcpu
,
sys_reg_descs
,
ARRAY_SIZE
(
sys_reg_descs
));
table
=
get_target_table
(
vcpu
->
arch
.
target
,
true
,
&
num
);
reset_sys_reg_descs
(
vcpu
,
table
,
num
);
}
arch/arm64/kvm/sys_regs_generic_v8.c
deleted
100644 → 0
View file @
fc279329
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2012,2013 - ARM Ltd
* Author: Marc Zyngier <marc.zyngier@arm.com>
*
* Based on arch/arm/kvm/coproc_a15.c:
* Copyright (C) 2012 - Virtual Open Systems and Columbia University
* Authors: Rusty Russell <rusty@rustcorp.au>
* Christoffer Dall <c.dall@virtualopensystems.com>
*/
#include <linux/kvm_host.h>
#include <asm/cputype.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_emulate.h>
#include <asm/kvm_coproc.h>
#include <asm/sysreg.h>
#include <linux/init.h>
#include "sys_regs.h"
static
bool
access_actlr
(
struct
kvm_vcpu
*
vcpu
,
struct
sys_reg_params
*
p
,
const
struct
sys_reg_desc
*
r
)
{
if
(
p
->
is_write
)
return
ignore_write
(
vcpu
,
p
);
p
->
regval
=
vcpu_read_sys_reg
(
vcpu
,
ACTLR_EL1
);
if
(
p
->
is_aarch32
)
{
if
(
r
->
Op2
&
2
)
p
->
regval
=
upper_32_bits
(
p
->
regval
);
else
p
->
regval
=
lower_32_bits
(
p
->
regval
);
}
return
true
;
}
static
void
reset_actlr
(
struct
kvm_vcpu
*
vcpu
,
const
struct
sys_reg_desc
*
r
)
{
__vcpu_sys_reg
(
vcpu
,
ACTLR_EL1
)
=
read_sysreg
(
actlr_el1
);
}
/*
* Implementation specific sys-reg registers.
* Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
*/
static
const
struct
sys_reg_desc
genericv8_sys_regs
[]
=
{
{
SYS_DESC
(
SYS_ACTLR_EL1
),
access_actlr
,
reset_actlr
,
ACTLR_EL1
},
};
static
const
struct
sys_reg_desc
genericv8_cp15_regs
[]
=
{
/* ACTLR */
{
Op1
(
0
b000
),
CRn
(
0
b0001
),
CRm
(
0
b0000
),
Op2
(
0
b001
),
access_actlr
},
{
Op1
(
0
b000
),
CRn
(
0
b0001
),
CRm
(
0
b0000
),
Op2
(
0
b011
),
access_actlr
},
};
static
struct
kvm_sys_reg_target_table
genericv8_target_table
=
{
.
table64
=
{
.
table
=
genericv8_sys_regs
,
.
num
=
ARRAY_SIZE
(
genericv8_sys_regs
),
},
.
table32
=
{
.
table
=
genericv8_cp15_regs
,
.
num
=
ARRAY_SIZE
(
genericv8_cp15_regs
),
},
};
static
int
__init
sys_reg_genericv8_init
(
void
)
{
unsigned
int
i
;
for
(
i
=
1
;
i
<
ARRAY_SIZE
(
genericv8_sys_regs
);
i
++
)
BUG_ON
(
cmp_sys_reg
(
&
genericv8_sys_regs
[
i
-
1
],
&
genericv8_sys_regs
[
i
])
>=
0
);
kvm_register_target_sys_reg_table
(
KVM_ARM_TARGET_AEM_V8
,
&
genericv8_target_table
);
kvm_register_target_sys_reg_table
(
KVM_ARM_TARGET_FOUNDATION_V8
,
&
genericv8_target_table
);
kvm_register_target_sys_reg_table
(
KVM_ARM_TARGET_CORTEX_A53
,
&
genericv8_target_table
);
kvm_register_target_sys_reg_table
(
KVM_ARM_TARGET_CORTEX_A57
,
&
genericv8_target_table
);
kvm_register_target_sys_reg_table
(
KVM_ARM_TARGET_XGENE_POTENZA
,
&
genericv8_target_table
);
kvm_register_target_sys_reg_table
(
KVM_ARM_TARGET_GENERIC_V8
,
&
genericv8_target_table
);
return
0
;
}
late_initcall
(
sys_reg_genericv8_init
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment