mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
Revert "ANDROID: KVM: arm64: s2mpu: Move mpt_update_flags into FMPT"
This reverts commit 2927077b47.
Bug: 233587962
Signed-off-by: Will Deacon <willdeacon@google.com>
Change-Id: I1b74b276d0d7bd04f56b0ff194340e495b6f7e5f
This commit is contained in:
@@ -160,22 +160,21 @@ static const u64 mpt_prot_doubleword[] = {
|
||||
[MPT_PROT_RW] = 0xffffffffffffffff,
|
||||
};
|
||||
|
||||
enum mpt_update_flags {
|
||||
MPT_UPDATE_L1 = BIT(0),
|
||||
MPT_UPDATE_L2 = BIT(1),
|
||||
};
|
||||
|
||||
struct fmpt {
|
||||
u32 *smpt;
|
||||
bool gran_1g;
|
||||
enum mpt_prot prot;
|
||||
enum mpt_update_flags flags;
|
||||
};
|
||||
|
||||
struct mpt {
|
||||
struct fmpt fmpt[NR_GIGABYTES];
|
||||
};
|
||||
|
||||
enum mpt_update_flags {
|
||||
MPT_UPDATE_L1 = BIT(0),
|
||||
MPT_UPDATE_L2 = BIT(1),
|
||||
};
|
||||
|
||||
/* Set protection bits of SMPT in a given range without using memset. */
|
||||
static inline void __set_smpt_range_slow(u32 *smpt, size_t start_gb_byte,
|
||||
size_t end_gb_byte, enum mpt_prot prot)
|
||||
@@ -255,28 +254,24 @@ static inline bool __is_smpt_uniform(u32 *smpt, enum mpt_prot prot)
|
||||
* Returns flags specifying whether L1/L2 changes need to be made visible
|
||||
* to the device.
|
||||
*/
|
||||
static inline void __set_fmpt_range(struct fmpt *fmpt, size_t start_gb_byte,
|
||||
size_t end_gb_byte, enum mpt_prot prot)
|
||||
static inline enum mpt_update_flags
|
||||
__set_fmpt_range(struct fmpt *fmpt, size_t start_gb_byte, size_t end_gb_byte,
|
||||
enum mpt_prot prot)
|
||||
{
|
||||
if (start_gb_byte == 0 && end_gb_byte >= SZ_1G) {
|
||||
/* Update covers the entire GB region. */
|
||||
if (fmpt->gran_1g && fmpt->prot == prot) {
|
||||
fmpt->flags = 0;
|
||||
return;
|
||||
}
|
||||
if (fmpt->gran_1g && fmpt->prot == prot)
|
||||
return 0;
|
||||
|
||||
fmpt->gran_1g = true;
|
||||
fmpt->prot = prot;
|
||||
fmpt->flags = MPT_UPDATE_L1;
|
||||
return;
|
||||
return MPT_UPDATE_L1;
|
||||
}
|
||||
|
||||
if (fmpt->gran_1g) {
|
||||
/* GB region currently uses 1G mapping. */
|
||||
if (fmpt->prot == prot) {
|
||||
fmpt->flags = 0;
|
||||
return;
|
||||
}
|
||||
if (fmpt->prot == prot)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Range has different mapping than the rest of the GB.
|
||||
@@ -286,22 +281,19 @@ static inline void __set_fmpt_range(struct fmpt *fmpt, size_t start_gb_byte,
|
||||
__set_smpt_range(fmpt->smpt, 0, start_gb_byte, fmpt->prot);
|
||||
__set_smpt_range(fmpt->smpt, start_gb_byte, end_gb_byte, prot);
|
||||
__set_smpt_range(fmpt->smpt, end_gb_byte, SZ_1G, fmpt->prot);
|
||||
fmpt->flags = MPT_UPDATE_L1 | MPT_UPDATE_L2;
|
||||
return;
|
||||
return MPT_UPDATE_L1 | MPT_UPDATE_L2;
|
||||
}
|
||||
|
||||
/* GB region currently uses PAGE_SIZE mapping. */
|
||||
__set_smpt_range(fmpt->smpt, start_gb_byte, end_gb_byte, prot);
|
||||
|
||||
/* Check if the entire GB region has the same prot bits. */
|
||||
if (!__is_smpt_uniform(fmpt->smpt, prot)) {
|
||||
fmpt->flags = MPT_UPDATE_L2;
|
||||
return;
|
||||
}
|
||||
if (!__is_smpt_uniform(fmpt->smpt, prot))
|
||||
return MPT_UPDATE_L2;
|
||||
|
||||
fmpt->gran_1g = true;
|
||||
fmpt->prot = prot;
|
||||
fmpt->flags = MPT_UPDATE_L1;
|
||||
return MPT_UPDATE_L1;
|
||||
}
|
||||
|
||||
#endif /* __ARM64_KVM_S2MPU_H__ */
|
||||
|
||||
@@ -285,18 +285,19 @@ static void set_mpt_range_locked(struct mpt *mpt, phys_addr_t first_byte,
|
||||
unsigned int gb, vid;
|
||||
struct pkvm_iommu *dev;
|
||||
struct fmpt *fmpt;
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
for_each_gb_in_range(gb, first_gb, last_gb) {
|
||||
fmpt = &mpt->fmpt[gb];
|
||||
start_gb_byte = (gb == first_gb) ? first_byte % SZ_1G : 0;
|
||||
end_gb_byte = (gb == last_gb) ? (last_byte % SZ_1G) + 1 : SZ_1G;
|
||||
|
||||
__set_fmpt_range(fmpt, start_gb_byte, end_gb_byte, prot);
|
||||
flags = __set_fmpt_range(fmpt, start_gb_byte, end_gb_byte, prot);
|
||||
|
||||
if (fmpt->flags & MPT_UPDATE_L2)
|
||||
if (flags & MPT_UPDATE_L2)
|
||||
kvm_flush_dcache_to_poc(fmpt->smpt, SMPT_SIZE);
|
||||
|
||||
if (fmpt->flags & MPT_UPDATE_L1) {
|
||||
if (flags & MPT_UPDATE_L1) {
|
||||
for_each_powered_s2mpu(dev) {
|
||||
for_each_vid(vid)
|
||||
__set_l1entry_attr_with_fmpt(dev, gb, vid, fmpt);
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
|
||||
KSTM_MODULE_GLOBALS();
|
||||
|
||||
/*
|
||||
* Kernel module for testing the foobinator
|
||||
*/
|
||||
|
||||
#define ASSERT(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
@@ -73,9 +77,11 @@ static bool __init check_smpt(size_t start_byte, size_t end_byte,
|
||||
/* Start with 1G granule, overwrite the whole 1G. */
|
||||
static int __init test_set_fmpt__fmpt_to_fmpt_whole(void)
|
||||
{
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
init_fmpt(MPT_PROT_NONE, /*gran_1g*/ true);
|
||||
__set_fmpt_range(&g_fmpt, 0, SZ_1G, MPT_PROT_R);
|
||||
ASSERT(g_fmpt.flags == MPT_UPDATE_L1);
|
||||
flags = __set_fmpt_range(&g_fmpt, 0, SZ_1G, MPT_PROT_R);
|
||||
ASSERT(flags == MPT_UPDATE_L1);
|
||||
ASSERT(g_fmpt.gran_1g);
|
||||
ASSERT(g_fmpt.prot == MPT_PROT_R);
|
||||
return 0;
|
||||
@@ -84,9 +90,11 @@ static int __init test_set_fmpt__fmpt_to_fmpt_whole(void)
|
||||
/* Start with 1G granule, overwrite the whole 1G with the same prot. */
|
||||
static int __init test_set_fmpt__fmpt_no_change_whole(void)
|
||||
{
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
init_fmpt(MPT_PROT_R, /*gran_1g*/ true);
|
||||
__set_fmpt_range(&g_fmpt, 0, SZ_1G, MPT_PROT_R);
|
||||
ASSERT(g_fmpt.flags == 0);
|
||||
flags = __set_fmpt_range(&g_fmpt, 0, SZ_1G, MPT_PROT_R);
|
||||
ASSERT(flags == 0);
|
||||
ASSERT(g_fmpt.gran_1g);
|
||||
ASSERT(g_fmpt.prot == MPT_PROT_R);
|
||||
return 0;
|
||||
@@ -95,9 +103,11 @@ static int __init test_set_fmpt__fmpt_no_change_whole(void)
|
||||
/* Start with 1G granule, partially overwrite with the same prot. */
|
||||
static int __init test_set_fmpt__fmpt_no_change_partial(void)
|
||||
{
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
init_fmpt(MPT_PROT_R, /*gran_1g*/ true);
|
||||
__set_fmpt_range(&g_fmpt, 0, PAGE_SIZE, MPT_PROT_R);
|
||||
ASSERT(g_fmpt.flags == 0);
|
||||
flags = __set_fmpt_range(&g_fmpt, 0, PAGE_SIZE, MPT_PROT_R);
|
||||
ASSERT(flags == 0);
|
||||
ASSERT(g_fmpt.gran_1g);
|
||||
ASSERT(g_fmpt.prot == MPT_PROT_R);
|
||||
return 0;
|
||||
@@ -108,10 +118,11 @@ static int __init test_set_fmpt__fmpt_to_smpt(void)
|
||||
{
|
||||
size_t start = 5 * SMPT_WORD_BYTE_RANGE / 2;
|
||||
size_t end = 20 * SMPT_WORD_BYTE_RANGE;
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
init_fmpt(MPT_PROT_R, /*gran_1g*/ true);
|
||||
__set_fmpt_range(&g_fmpt, start, end, MPT_PROT_RW);
|
||||
ASSERT(g_fmpt.flags == (MPT_UPDATE_L1 | MPT_UPDATE_L2));
|
||||
flags = __set_fmpt_range(&g_fmpt, start, end, MPT_PROT_RW);
|
||||
ASSERT(flags == (MPT_UPDATE_L1 | MPT_UPDATE_L2));
|
||||
ASSERT(!g_fmpt.gran_1g);
|
||||
return check_smpt(start, end, MPT_PROT_R, MPT_PROT_RW) ? 0 : 1;
|
||||
}
|
||||
@@ -119,9 +130,11 @@ static int __init test_set_fmpt__fmpt_to_smpt(void)
|
||||
/* Convert from PAGE_SIZE to 1G granule by overwriting the whole 1G. */
|
||||
static int __init test_set_fmpt__smpt_to_fmpt_whole(void)
|
||||
{
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
init_fmpt(MPT_PROT_NONE, /*gran_1g*/ false);
|
||||
__set_fmpt_range(&g_fmpt, 0, SZ_1G, MPT_PROT_R);
|
||||
ASSERT(g_fmpt.flags == MPT_UPDATE_L1);
|
||||
flags = __set_fmpt_range(&g_fmpt, 0, SZ_1G, MPT_PROT_R);
|
||||
ASSERT(flags == MPT_UPDATE_L1);
|
||||
ASSERT(g_fmpt.gran_1g);
|
||||
ASSERT(g_fmpt.prot == MPT_PROT_R);
|
||||
return 0;
|
||||
@@ -132,14 +145,15 @@ static int __init test_set_fmpt__smpt_to_fmpt_partial(void)
|
||||
{
|
||||
size_t start = 5 * SMPT_WORD_BYTE_RANGE / 2;
|
||||
size_t end = 20 * SMPT_WORD_BYTE_RANGE;
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
/* Create SMPT with all PROT_W except a small subrange. */
|
||||
init_fmpt(MPT_PROT_W, /*gran_1g*/ false);
|
||||
__set_smpt_range(g_smpt, start, end, MPT_PROT_RW);
|
||||
|
||||
/* Fill the subrange with PROT_W to make the SMPT uniform. */
|
||||
__set_fmpt_range(&g_fmpt, start, end, MPT_PROT_W);
|
||||
ASSERT(g_fmpt.flags == MPT_UPDATE_L1);
|
||||
flags = __set_fmpt_range(&g_fmpt, start, end, MPT_PROT_W);
|
||||
ASSERT(flags == MPT_UPDATE_L1);
|
||||
ASSERT(g_fmpt.gran_1g);
|
||||
ASSERT(g_fmpt.prot == MPT_PROT_W);
|
||||
return 0;
|
||||
@@ -150,13 +164,14 @@ static int __init test_set_fmpt__smpt_to_smpt(void)
|
||||
{
|
||||
size_t start = SZ_1G - SMPT_GRAN;
|
||||
size_t end = SZ_1G;
|
||||
enum mpt_update_flags flags;
|
||||
|
||||
init_fmpt(MPT_PROT_NONE, /*gran_1g*/ false);
|
||||
ASSERT(__is_smpt_uniform(g_smpt, MPT_PROT_NONE));
|
||||
|
||||
/* Fill the subrange with PROT_W to make the SMPT uniform. */
|
||||
__set_fmpt_range(&g_fmpt, start, end, MPT_PROT_RW);
|
||||
ASSERT(g_fmpt.flags == MPT_UPDATE_L2);
|
||||
flags = __set_fmpt_range(&g_fmpt, start, end, MPT_PROT_RW);
|
||||
ASSERT(flags == MPT_UPDATE_L2);
|
||||
ASSERT(!g_fmpt.gran_1g);
|
||||
ASSERT(!__is_smpt_uniform(g_smpt, MPT_PROT_NONE));
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user