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:
Hector Martin 2021-11-02 15:24:26 +09:00
parent dc3806252b
commit 8fa422c0d3
5 changed files with 40 additions and 10 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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");

View file

@ -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) |

View file

@ -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__