Fix ARM cache maintainance.
More code was converted from ASM to C for easier handling.
This commit is contained in:
parent
adabfb5418
commit
943981ff65
3 changed files with 44 additions and 38 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2013-12-23 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Fix ARM cache maintainance.
|
||||||
|
|
||||||
|
More code was converted from ASM to C for easier handling.
|
||||||
|
|
||||||
2013-12-22 Vladimir Serbinenko <phcoder@gmail.com>
|
2013-12-22 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/kern/arm/cache.c (grub_arm_disable_caches_mmu): Use v6
|
* grub-core/kern/arm/cache.c (grub_arm_disable_caches_mmu): Use v6
|
||||||
|
|
|
@ -37,20 +37,16 @@
|
||||||
* Simple cache maintenance functions
|
* Simple cache maintenance functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dlinesz_addr:
|
|
||||||
.long EXT_C(grub_arch_cache_dlinesz)
|
|
||||||
ilinesz_addr:
|
|
||||||
.long EXT_C(grub_arch_cache_ilinesz)
|
|
||||||
|
|
||||||
@ r0 - *beg (inclusive)
|
@ r0 - *beg (inclusive)
|
||||||
@ r1 - *end (exclusive)
|
@ r1 - *end (exclusive)
|
||||||
clean_dcache_range:
|
@void grub_arm_clean_dcache_range (grub_addr_t start, grub_addr_t end, grub_addr_t dlinesz)
|
||||||
|
#ifdef ARMV6
|
||||||
|
FUNCTION(grub_arm_clean_dcache_range_armv6)
|
||||||
|
#else
|
||||||
|
FUNCTION(grub_arm_clean_dcache_range_armv7)
|
||||||
|
#endif
|
||||||
|
DSB
|
||||||
@ Clean data cache for range to point-of-unification
|
@ Clean data cache for range to point-of-unification
|
||||||
ldr r2, dlinesz_addr
|
|
||||||
ldr r2, [r2]
|
|
||||||
sub r3, r2, #1 @ align "beg" to start of line
|
|
||||||
mvn r3, r3
|
|
||||||
and r0, r0, r3
|
|
||||||
1: cmp r0, r1
|
1: cmp r0, r1
|
||||||
bge 2f
|
bge 2f
|
||||||
#ifdef ARMV6
|
#ifdef ARMV6
|
||||||
|
@ -65,13 +61,12 @@ clean_dcache_range:
|
||||||
|
|
||||||
@ r0 - *beg (inclusive)
|
@ r0 - *beg (inclusive)
|
||||||
@ r1 - *end (exclusive)
|
@ r1 - *end (exclusive)
|
||||||
invalidate_icache_range:
|
#ifdef ARMV6
|
||||||
|
FUNCTION(grub_arm_invalidate_icache_range_armv6)
|
||||||
|
#else
|
||||||
|
FUNCTION(grub_arm_invalidate_icache_range_armv7)
|
||||||
|
#endif
|
||||||
@ Invalidate instruction cache for range to point-of-unification
|
@ Invalidate instruction cache for range to point-of-unification
|
||||||
ldr r2, ilinesz_addr
|
|
||||||
ldr r2, [r2]
|
|
||||||
sub r3, r2, #1 @ align "beg" to start of line
|
|
||||||
mvn r3, r3
|
|
||||||
and r0, r0, r3
|
|
||||||
1: cmp r0, r1
|
1: cmp r0, r1
|
||||||
bge 2f
|
bge 2f
|
||||||
mcr p15, 0, r0, c7, c5, 1 @ ICIMVAU
|
mcr p15, 0, r0, c7, c5, 1 @ ICIMVAU
|
||||||
|
@ -83,21 +78,6 @@ invalidate_icache_range:
|
||||||
ISB
|
ISB
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
@void grub_arch_sync_caches (void *address, grub_size_t len)
|
|
||||||
#ifdef ARMV6
|
|
||||||
FUNCTION(grub_arch_sync_caches_armv6)
|
|
||||||
#else
|
|
||||||
FUNCTION(grub_arch_sync_caches_armv7)
|
|
||||||
#endif
|
|
||||||
DSB
|
|
||||||
add r1, r0, r1
|
|
||||||
push {r0-r2, lr}
|
|
||||||
bl clean_dcache_range
|
|
||||||
pop {r0, r1}
|
|
||||||
bl invalidate_icache_range
|
|
||||||
pop {r2, lr}
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
#ifdef ARMV6
|
#ifdef ARMV6
|
||||||
FUNCTION(grub_arm_disable_caches_mmu_armv6)
|
FUNCTION(grub_arm_disable_caches_mmu_armv6)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -13,12 +13,19 @@ static enum
|
||||||
ARCH_ARMV7
|
ARCH_ARMV7
|
||||||
} type = ARCH_UNKNOWN;
|
} type = ARCH_UNKNOWN;
|
||||||
|
|
||||||
grub_uint32_t grub_arch_cache_dlinesz;
|
static grub_uint32_t grub_arch_cache_dlinesz;
|
||||||
grub_uint32_t grub_arch_cache_ilinesz;
|
static grub_uint32_t grub_arch_cache_ilinesz;
|
||||||
|
static grub_uint32_t grub_arch_cache_max_linesz;
|
||||||
|
|
||||||
/* Prototypes for asm functions. */
|
/* Prototypes for asm functions. */
|
||||||
void grub_arch_sync_caches_armv6 (void *address, grub_size_t len);
|
void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end,
|
||||||
void grub_arch_sync_caches_armv7 (void *address, grub_size_t len);
|
grub_addr_t dlinesz);
|
||||||
|
void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end,
|
||||||
|
grub_addr_t dlinesz);
|
||||||
|
void grub_arm_invalidate_icache_range_armv6 (grub_addr_t start, grub_addr_t end,
|
||||||
|
grub_addr_t dlinesz);
|
||||||
|
void grub_arm_invalidate_icache_range_armv7 (grub_addr_t start, grub_addr_t end,
|
||||||
|
grub_addr_t dlinesz);
|
||||||
void grub_arm_disable_caches_mmu_armv6 (void);
|
void grub_arm_disable_caches_mmu_armv6 (void);
|
||||||
void grub_arm_disable_caches_mmu_armv7 (void);
|
void grub_arm_disable_caches_mmu_armv7 (void);
|
||||||
grub_uint32_t grub_arm_main_id (void);
|
grub_uint32_t grub_arm_main_id (void);
|
||||||
|
@ -82,20 +89,33 @@ probe_caches (void)
|
||||||
default:
|
default:
|
||||||
grub_fatal ("Unsupported cache type 0x%x", cache_type);
|
grub_fatal ("Unsupported cache type 0x%x", cache_type);
|
||||||
}
|
}
|
||||||
|
if (grub_arch_cache_dlinesz > grub_arch_cache_ilinesz)
|
||||||
|
grub_arch_cache_max_linesz = grub_arch_cache_dlinesz;
|
||||||
|
else
|
||||||
|
grub_arch_cache_max_linesz = grub_arch_cache_ilinesz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_arch_sync_caches (void *address, grub_size_t len)
|
grub_arch_sync_caches (void *address, grub_size_t len)
|
||||||
{
|
{
|
||||||
|
grub_addr_t start = (grub_addr_t) address;
|
||||||
|
grub_addr_t end = start + len;
|
||||||
|
|
||||||
if (type == ARCH_UNKNOWN)
|
if (type == ARCH_UNKNOWN)
|
||||||
probe_caches ();
|
probe_caches ();
|
||||||
|
start = ALIGN_DOWN (start, grub_arch_cache_max_linesz);
|
||||||
|
end = ALIGN_UP (end, grub_arch_cache_max_linesz);
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ARCH_ARMV6:
|
case ARCH_ARMV6:
|
||||||
grub_arch_sync_caches_armv6 (address, len);
|
grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
|
||||||
|
grub_arm_invalidate_icache_range_armv6 (start, end,
|
||||||
|
grub_arch_cache_ilinesz);
|
||||||
break;
|
break;
|
||||||
case ARCH_ARMV7:
|
case ARCH_ARMV7:
|
||||||
grub_arch_sync_caches_armv7 (address, len);
|
grub_arm_clean_dcache_range_armv7 (start, end, grub_arch_cache_dlinesz);
|
||||||
|
grub_arm_invalidate_icache_range_armv7 (start, end,
|
||||||
|
grub_arch_cache_ilinesz);
|
||||||
break;
|
break;
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
case ARCH_ARMV5_WRITE_THROUGH:
|
case ARCH_ARMV5_WRITE_THROUGH:
|
||||||
|
|
Loading…
Reference in a new issue