mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 09:44:13 +00:00
fb: Map the framebuffer uncached, and use a shadow FB for speed
Turns out AMCC on t600x throws errors when DISP0 real-time memory requests hit the CPU cache, and then macOS panics. Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
dc3806252b
commit
8fa422c0d3
5 changed files with 40 additions and 10 deletions
31
src/fb.c
31
src/fb.c
|
@ -65,13 +65,18 @@ const struct image logo_256 = {
|
|||
const struct image *logo;
|
||||
struct image orig_logo;
|
||||
|
||||
void fb_update(void)
|
||||
{
|
||||
memcpy(fb.hwptr, fb.ptr, fb.size);
|
||||
}
|
||||
|
||||
static void fb_clear_font_row(u32 row)
|
||||
{
|
||||
const u32 row_size = (console.margin.cols + console.cursor.max_col) * console.font.width * 4;
|
||||
const u32 ystart = (console.margin.rows + row) * console.font.height * fb.stride;
|
||||
|
||||
for (u32 y = 0; y < console.font.height; ++y)
|
||||
memset(fb.ptr + ystart + y * fb.stride, 0, row_size);
|
||||
memset32(fb.ptr + ystart + y * fb.stride, 0, row_size);
|
||||
}
|
||||
|
||||
static void fb_move_font_row(u32 dst, u32 src)
|
||||
|
@ -84,7 +89,7 @@ static void fb_move_font_row(u32 dst, u32 src)
|
|||
ydst *= fb.stride;
|
||||
|
||||
for (u32 y = 0; y < console.font.height; ++y)
|
||||
memcpy(fb.ptr + ydst + y * fb.stride, fb.ptr + ysrc + y * fb.stride, row_size);
|
||||
memcpy32(fb.ptr + ydst + y * fb.stride, fb.ptr + ysrc + y * fb.stride, row_size);
|
||||
|
||||
fb_clear_font_row(src);
|
||||
}
|
||||
|
@ -121,6 +126,7 @@ void fb_blit(u32 x, u32 y, u32 w, u32 h, void *data, u32 stride)
|
|||
fb_set_pixel(x + j, y + i, color);
|
||||
}
|
||||
}
|
||||
fb_update();
|
||||
}
|
||||
|
||||
void fb_unblit(u32 x, u32 y, u32 w, u32 h, void *data, u32 stride)
|
||||
|
@ -143,12 +149,14 @@ void fb_fill(u32 x, u32 y, u32 w, u32 h, rgb_t color)
|
|||
u32 c = rgb2pixel_30(color);
|
||||
for (u32 i = 0; i < h; i++)
|
||||
memset32(&fb.ptr[x + (y + i) * fb.stride], c, w * 4);
|
||||
fb_update();
|
||||
}
|
||||
|
||||
void fb_clear(rgb_t color)
|
||||
{
|
||||
u32 c = rgb2pixel_30(color);
|
||||
memset32(fb.ptr, c, fb.stride * fb.height * 4);
|
||||
fb_update();
|
||||
}
|
||||
|
||||
void fb_blit_image(u32 x, u32 y, const struct image *img)
|
||||
|
@ -253,6 +261,7 @@ void fb_console_reserve_lines(u32 n)
|
|||
{
|
||||
if ((console.cursor.max_row - console.cursor.row) <= n)
|
||||
fb_console_scroll(1 + n - (console.cursor.max_row - console.cursor.row));
|
||||
fb_update();
|
||||
}
|
||||
|
||||
ssize_t fb_console_write(const char *bfr, size_t len)
|
||||
|
@ -267,6 +276,8 @@ ssize_t fb_console_write(const char *bfr, size_t len)
|
|||
wrote++;
|
||||
}
|
||||
|
||||
fb_update();
|
||||
|
||||
return wrote;
|
||||
}
|
||||
|
||||
|
@ -296,20 +307,27 @@ static void fb_clear_console(void)
|
|||
{
|
||||
for (u32 row = 0; row < console.cursor.max_row; ++row)
|
||||
fb_clear_font_row(row);
|
||||
|
||||
console.cursor.col = 0;
|
||||
console.cursor.row = 0;
|
||||
fb_update();
|
||||
}
|
||||
|
||||
void fb_init(void)
|
||||
{
|
||||
fb.ptr = (void *)cur_boot_args.video.base;
|
||||
fb.hwptr = (void *)cur_boot_args.video.base;
|
||||
fb.stride = cur_boot_args.video.stride / 4;
|
||||
fb.width = cur_boot_args.video.width;
|
||||
fb.height = cur_boot_args.video.height;
|
||||
fb.depth = cur_boot_args.video.depth & FB_DEPTH_MASK;
|
||||
fb.size = cur_boot_args.video.stride * cur_boot_args.video.height;
|
||||
printf("fb init: %dx%d (%d) [s=%d] @%p\n", fb.width, fb.height, fb.depth, fb.stride, fb.ptr);
|
||||
|
||||
uint64_t fb_size = cur_boot_args.video.stride * cur_boot_args.video.height;
|
||||
mmu_add_mapping(cur_boot_args.video.base, cur_boot_args.video.base, ALIGN_UP(fb_size, 0x4000),
|
||||
MAIR_IDX_NORMAL, PERM_RWX);
|
||||
mmu_add_mapping(cur_boot_args.video.base, cur_boot_args.video.base, ALIGN_UP(fb.size, 0x4000),
|
||||
MAIR_IDX_FRAMEBUFFER, PERM_RW);
|
||||
|
||||
fb.ptr = malloc(fb.size);
|
||||
memcpy(fb.ptr, fb.hwptr, fb.size);
|
||||
|
||||
if (cur_boot_args.video.depth & FB_DEPTH_FLAG_RETINA) {
|
||||
logo = &logo_256;
|
||||
|
@ -359,4 +377,5 @@ void fb_shutdown(bool restore_logo)
|
|||
free(orig_logo.ptr);
|
||||
orig_logo.ptr = NULL;
|
||||
}
|
||||
free(fb.ptr);
|
||||
}
|
||||
|
|
3
src/fb.h
3
src/fb.h
|
@ -7,10 +7,12 @@
|
|||
|
||||
typedef struct {
|
||||
u32 *ptr; /* pointer to the start of the framebuffer */
|
||||
u32 *hwptr; /* pointer to the start of the real framebuffer */
|
||||
u32 stride; /* framebuffer stride divided by four (i.e. stride in pixels) */
|
||||
u32 depth; /* framebuffer depth (i.e. bits per pixel) */
|
||||
u32 width; /* width of the framebuffer in pixels */
|
||||
u32 height; /* height of the framebuffer in pixels */
|
||||
u32 size; /* size of the framebuffer in bytes */
|
||||
} fb_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -28,6 +30,7 @@ static inline rgb_t int2rgb(u32 c)
|
|||
|
||||
void fb_init(void);
|
||||
void fb_shutdown(bool restore_logo);
|
||||
void fb_update(void);
|
||||
|
||||
void fb_blit(u32 x, u32 y, u32 w, u32 h, void *data, u32 stride);
|
||||
void fb_unblit(u32 x, u32 y, u32 w, u32 h, void *data, u32 stride);
|
||||
|
|
|
@ -106,10 +106,10 @@ void m1n1_main(void)
|
|||
|
||||
exception_shutdown();
|
||||
usb_iodev_shutdown();
|
||||
mmu_shutdown();
|
||||
#ifdef USE_FB
|
||||
fb_shutdown(next_stage.restore_logo);
|
||||
#endif
|
||||
mmu_shutdown();
|
||||
|
||||
printf("Vectoring to next stage...\n");
|
||||
|
||||
|
|
10
src/memory.c
10
src/memory.c
|
@ -149,6 +149,7 @@ enum SPRR_val_t {
|
|||
#define MAIR_SHIFT_NORMAL (MAIR_IDX_NORMAL * 8)
|
||||
#define MAIR_SHIFT_DEVICE_nGnRnE (MAIR_IDX_DEVICE_nGnRnE * 8)
|
||||
#define MAIR_SHIFT_DEVICE_nGnRE (MAIR_IDX_DEVICE_nGnRE * 8)
|
||||
#define MAIR_SHIFT_FRAMEBUFFER (MAIR_IDX_FRAMEBUFFER * 8)
|
||||
|
||||
/*
|
||||
* https://developer.arm.com/documentation/ddi0500/e/system-control/aarch64-register-descriptions/memory-attribute-indirection-register--el1
|
||||
|
@ -161,6 +162,7 @@ enum SPRR_val_t {
|
|||
#define MAIR_ATTR_NORMAL_DEFAULT 0xffUL
|
||||
#define MAIR_ATTR_DEVICE_nGnRnE 0x00UL
|
||||
#define MAIR_ATTR_DEVICE_nGnRE 0x04UL
|
||||
#define MAIR_ATTR_FRAMEBUFFER 0x44UL
|
||||
|
||||
static u64 mmu_pt_L0[2] ALIGNED(PAGE_SIZE);
|
||||
static u64 mmu_pt_L1[ENTRIES_PER_L1_TABLE] ALIGNED(PAGE_SIZE);
|
||||
|
@ -299,8 +301,9 @@ static void mmu_init_pagetables(void)
|
|||
|
||||
void mmu_add_mapping(u64 from, u64 to, size_t size, u8 attribute_index, u64 perms)
|
||||
{
|
||||
if (mmu_map(from, to | PTE_MAIR_IDX(attribute_index) | PTE_ACCESS | PTE_VALID | perms, size) <
|
||||
0)
|
||||
if (mmu_map(from,
|
||||
to | PTE_MAIR_IDX(attribute_index) | PTE_ACCESS | PTE_VALID | PTE_SH_OS | perms,
|
||||
size) < 0)
|
||||
panic("Failed to add MMU mapping 0x%lx -> 0x%lx (0x%lx)\n", from, to, size);
|
||||
|
||||
sysop("dsb ishst");
|
||||
|
@ -473,7 +476,8 @@ static void mmu_configure(void)
|
|||
{
|
||||
msr(MAIR_EL1, (MAIR_ATTR_NORMAL_DEFAULT << MAIR_SHIFT_NORMAL) |
|
||||
(MAIR_ATTR_DEVICE_nGnRnE << MAIR_SHIFT_DEVICE_nGnRnE) |
|
||||
(MAIR_ATTR_DEVICE_nGnRE << MAIR_SHIFT_DEVICE_nGnRE));
|
||||
(MAIR_ATTR_DEVICE_nGnRE << MAIR_SHIFT_DEVICE_nGnRE) |
|
||||
(MAIR_ATTR_FRAMEBUFFER << MAIR_SHIFT_FRAMEBUFFER));
|
||||
msr(TCR_EL1, FIELD_PREP(TCR_IPS, TCR_IPS_4TB) | FIELD_PREP(TCR_TG1, TCR_TG1_16K) |
|
||||
FIELD_PREP(TCR_SH1, TCR_SH1_IS) | FIELD_PREP(TCR_ORGN1, TCR_ORGN1_WBWA) |
|
||||
FIELD_PREP(TCR_IRGN1, TCR_IRGN1_WBWA) | FIELD_PREP(TCR_T1SZ, TCR_T1SZ_48BIT) |
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#define PTE_UXN BIT(54)
|
||||
#define PTE_AP_RO BIT(7)
|
||||
#define PTE_AP_EL0 BIT(6)
|
||||
#define PTE_SH_NS (0b00 << 8)
|
||||
#define PTE_SH_OS (0b10 << 8)
|
||||
#define PTE_SH_IS (0b11 << 8)
|
||||
|
||||
#define PERM_RO_EL0 PTE_AP_EL0 | PTE_AP_RO | PTE_PXN | PTE_UXN
|
||||
#define PERM_RW_EL0 PTE_AP_EL0 | PTE_PXN | PTE_UXN
|
||||
|
@ -43,6 +46,7 @@
|
|||
#define MAIR_IDX_NORMAL 0
|
||||
#define MAIR_IDX_DEVICE_nGnRnE 1
|
||||
#define MAIR_IDX_DEVICE_nGnRE 2
|
||||
#define MAIR_IDX_FRAMEBUFFER 3
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
|
|
Loading…
Reference in a new issue