Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions arch/linx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@ export BITS
ifeq ($(CONFIG_ARCH_RV64I),y)
BITS := 64
UTS_MACHINE := linx64

KBUILD_LDFLAGS += -melf64llinxv5
else
BITS := 32
UTS_MACHINE := linx32
endif

ifeq ($(CONFIG_LD_IS_LLD),y)
# The in-tree Linx LLD backend links ELF Linx objects correctly but does
# not accept GNU emulation strings like -melf64llinxv5. Let it infer the
# target from the input objects.
else ifeq ($(CONFIG_ARCH_RV64I),y)
KBUILD_LDFLAGS += -melf64llinxv5
else
KBUILD_LDFLAGS += -melf32llinxv5
endif

Expand All @@ -41,6 +48,11 @@ linx-march-$(CONFIG_RISCV_ISA_C) := $(linx-march-y)c
KBUILD_CFLAGS += -march=$(subst fd,,$(linx-march-y))
KBUILD_AFLAGS += -march=$(linx-march-y)

# Current Linx backend bring-up is not stable enough for large generic kernel
# loop/SLP vectorization. Disable those passes globally so unrelated drivers do
# not block serial-boot closure with backend crashes.
KBUILD_CFLAGS += -fno-vectorize -fno-slp-vectorize

KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
ifeq ($(CONFIG_PERF_EVENTS),y)
KBUILD_CFLAGS += -fno-omit-frame-pointer
Expand Down Expand Up @@ -72,8 +84,6 @@ else
KBUILD_IMAGE := $(boot)/Image.gz
endif

head-y := arch/linx/kernel/head.o

libs-y += arch/linx/lib/
libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

Expand Down
32 changes: 8 additions & 24 deletions arch/linx/configs/linx_v150_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,7 @@ CONFIG_SOC_VIRT=y
CONFIG_ARCH_RV64I=y
# CONFIG_CMODEL_MEDLOW is not set
CONFIG_CMODEL_MEDANY=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
# CONFIG_SMP is not set
# CONFIG_HOTPLUG_CPU is not set
CONFIG_TUNE_GENERIC=y
# CONFIG_NUMA is not set
Expand Down Expand Up @@ -2081,7 +2080,7 @@ CONFIG_MFD_SYSCON=y
#
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_DRM=y
# CONFIG_DRM is not set
# CONFIG_DRM_DP_AUX_CHARDEV is not set
# CONFIG_DRM_DEBUG_MM is not set
# CONFIG_DRM_DEBUG_SELFTEST is not set
Expand All @@ -2097,8 +2096,8 @@ CONFIG_DRM_GEM_SHMEM_HELPER=y
#
# I2C encoder or helper chips
#
CONFIG_DRM_I2C_CH7006=y
CONFIG_DRM_I2C_SIL164=y
# CONFIG_DRM_I2C_CH7006 is not set
# CONFIG_DRM_I2C_SIL164 is not set
# CONFIG_DRM_I2C_NXP_TDA998X is not set
# CONFIG_DRM_I2C_NXP_TDA9950 is not set
# end of I2C encoder or helper chips
Expand All @@ -2109,26 +2108,11 @@ CONFIG_DRM_I2C_SIL164=y
# CONFIG_DRM_KOMEDA is not set
# end of ARM devices

CONFIG_DRM_RADEON=y
# CONFIG_DRM_RADEON_USERPTR is not set
# CONFIG_DRM_RADEON is not set
# CONFIG_DRM_AMDGPU is not set
CONFIG_DRM_NOUVEAU=y
CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT=y
CONFIG_NOUVEAU_DEBUG=5
CONFIG_NOUVEAU_DEBUG_DEFAULT=3
# CONFIG_NOUVEAU_DEBUG_MMU is not set
# CONFIG_NOUVEAU_DEBUG_PUSH is not set
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
# CONFIG_DRM_VGEM is not set
# CONFIG_DRM_VKMS is not set
# CONFIG_DRM_UDL is not set
# CONFIG_DRM_AST is not set
# CONFIG_DRM_MGAG200 is not set
# CONFIG_DRM_RCAR_DW_HDMI is not set
# CONFIG_DRM_RCAR_LVDS is not set
# CONFIG_DRM_QXL is not set
CONFIG_DRM_VIRTIO_GPU=y
CONFIG_DRM_PANEL=y
# CONFIG_DRM_NOUVEAU is not set
# CONFIG_DRM_VIRTIO_GPU is not set
# CONFIG_DRM_PANEL is not set

#
# Display Panels
Expand Down
4 changes: 2 additions & 2 deletions arch/linx/include/asm/block-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@
.macro block_next_ind symbol
bstart.std ind
1: addtpc %tpcrel_hi(\symbol), -> t
addi t#1, %tpcrel_lo(1b), -> t
addi t#1, %tpcrel_lo(\symbol), -> t
setc.tgt t#1
bstop
.endm
Expand All @@ -304,7 +304,7 @@
.macro block_next_indcall symbol
bstart.std icall
1: addtpc %tpcrel_hi(\symbol), -> t
addi t#1, %tpcrel_lo(1b), -> t
addi t#1, %tpcrel_lo(\symbol), -> t
setc.tgt t#1
setret 2f, -> ra
bstop
Expand Down
8 changes: 7 additions & 1 deletion arch/linx/include/asm/cmpxchg.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,17 @@
* optional instruction atomic.order attribute, e.g. .rl
* @ret, @new, @old, @ptr:
* ret = *ptr, if (old == ret) *ptr = new, return @ret
*
* Current Linx LLVM inline-asm lowering rotates these named operands when
* materializing the final textual instruction, so the source string must be
* spelled as [%[n]], %[p], %[o] to emit the intended machine-order
* "[ptr], old, new". Keep this workaround local to the asm string until the
* backend contract is repaired.
*/
#define ASM_CMPXCHG(type, order, ret, new, old, ptr) \
__asm__ __volatile__ ( \
"BSTART.sys fall\n" \
"hl.cas" #type #order " [%[p]], %[o], %[n], -> %[r]\n" \
"hl.cas" #type #order " [%[n]], %[p], %[o], -> %[r]\n" \
: [r] "=&r" (ret) \
: [p] "r" (ptr), [o] "r" (old), [n] "r" (new) \
: "memory")
Expand Down
4 changes: 2 additions & 2 deletions arch/linx/include/asm/futex.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@
"b.attr aqrl \n" \
"" insn " \n" \
"2: \n" \
".section .fixup,\"ax\" \n" \
"BSTART.std direct, 4f \n" \
".balign 16 \n" \
"3: \n" \
"BSTART.std direct, 2b \n" \
"subi zero, %[e], -> %[r] \n" \
".previous \n" \
"4: \n" \
: [r] "+r" (ret), [ov] "=&r" (oldval) \
: [u] "r" (uaddr), [op] "r" (oparg), \
[e] "i" (EFAULT) \
Expand Down
6 changes: 5 additions & 1 deletion arch/linx/include/asm/irqflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ static inline int arch_irqs_disabled(void)
/* set interrupt enabled status */
static inline void arch_local_irq_restore(unsigned long flags)
{
ssr_set(SSR_CSTATE, flags & CSTATE_I);
unsigned long cstate = ssr_read(SSR_CSTATE);

cstate &= ~CSTATE_I;
cstate |= flags & CSTATE_I;
ssr_write(SSR_CSTATE, cstate);
}

#endif /* _ASM_LINX_IRQFLAGS_H */
48 changes: 43 additions & 5 deletions arch/linx/include/asm/pgtable-64.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ typedef struct {
#define __p4d(x) ((p4d_t) { (x) })
#define PTRS_PER_P4D (PAGE_SIZE / sizeof(p4d_t))

#if defined(__LINX__)
#define LINX_BOOT_PT_LOW_ALIAS_LIMIT _AC(64, UL) << 20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The macro LINX_BOOT_PT_LOW_ALIAS_LIMIT is defined using a shift operator (<<) without surrounding parentheses. In C, shift operators have lower precedence than additive operators (+, -). If this macro is ever used in an additive expression (e.g., LINX_BOOT_PT_LOW_ALIAS_LIMIT + offset), it will be evaluated incorrectly as 64UL << (20 + offset). Please wrap the macro definition in parentheses to ensure safe evaluation.

Suggested change
#define LINX_BOOT_PT_LOW_ALIAS_LIMIT _AC(64, UL) << 20
#define LINX_BOOT_PT_LOW_ALIAS_LIMIT (_AC(64, UL) << 20)


static inline bool linx_is_low_boot_pt_phys(unsigned long pa)
{
/*
* Linx bring-up allocates early page-table pages from a bounded low
* physical window. Treat that entire window as directly aliasable so
* early page-table walks do not depend on relocation-sensitive global
* state to decide between low alias and __va().
*/
return pa < LINX_BOOT_PT_LOW_ALIAS_LIMIT;
}
#endif

/* Page Upper Directory entry */
typedef struct {
unsigned long pud;
Expand Down Expand Up @@ -109,7 +124,14 @@ static inline unsigned long _pud_pfn(pud_t pud)

static inline pmd_t *pud_pgtable(pud_t pud)
{
return (pmd_t *)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT);
unsigned long pa = pfn_to_phys(_pud_pfn(pud));

#if defined(__LINX__)
if (linx_is_low_boot_pt_phys(pa))
return (pmd_t *)(uintptr_t)pa;
#endif

return (pmd_t *)__va(pa);
}

static inline struct page *pud_page(pud_t pud)
Expand Down Expand Up @@ -208,8 +230,16 @@ static inline unsigned long _p4d_pfn(p4d_t p4d)

static inline pud_t *p4d_pgtable(p4d_t p4d)
{
if (pgtable_l4_enabled)
return (pud_t *)pfn_to_virt(p4d_val(p4d) >> _PAGE_PFN_SHIFT);
if (pgtable_l4_enabled) {
unsigned long pa = pfn_to_phys(_p4d_pfn(p4d));

#if defined(__LINX__)
if (linx_is_low_boot_pt_phys(pa))
return (pud_t *)(uintptr_t)pa;
#endif

return (pud_t *)__va(pa);
}

return (pud_t *)pud_pgtable((pud_t) { p4d_val(p4d) });
}
Expand Down Expand Up @@ -272,8 +302,16 @@ static inline void pgd_clear(pgd_t *pgd)

static inline p4d_t *pgd_pgtable(pgd_t pgd)
{
if (pgtable_l5_enabled)
return (p4d_t *)pfn_to_virt(pgd_val(pgd) >> _PAGE_PFN_SHIFT);
if (pgtable_l5_enabled) {
unsigned long pa = pfn_to_phys(pgd_val(pgd) >> _PAGE_PFN_SHIFT);

#if defined(__LINX__)
if (linx_is_low_boot_pt_phys(pa))
return (p4d_t *)(uintptr_t)pa;
#endif

return (p4d_t *)__va(pa);
}

return (p4d_t *)p4d_pgtable((p4d_t) { pgd_val(pgd) });
}
Expand Down
6 changes: 6 additions & 0 deletions arch/linx/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ struct thread_struct {
unsigned long ra;
unsigned long sp; /* Kernel mode stack */
unsigned long s[9]; /* s[0]: frame pointer */
/*
* ACR1 EBSTATE switch window.
* Save the full 0x1f40..0x1f5f register range so schedule()/__switch_to()
* can round-trip in-flight block state without needing per-field policy.
*/
unsigned long ebstate[32];
struct __riscv_d_ext_state fstate;
unsigned long bad_cause;
};
Expand Down
89 changes: 71 additions & 18 deletions arch/linx/include/asm/ssr.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,33 @@
#define SSR_A0_XBINFO 0x0f30 /* acr0's XB base register */
#define SSR_A0_ACR_PARAM 0x0f31 /* acr0's LxLc argument register */

#define SSR_A0_ELPR0 0x0f40 /* acr0's exception t1 */
#define SSR_A0_ELPR1 0x0f41 /* acr0's exception t2 */
#define SSR_A0_ELPR2 0x0f42 /* acr0's exception t3 */
#define SSR_A0_ELPR3 0x0f43 /* acr0's exception t4 */
#define SSR_A0_ELPR4 0x0f44 /* acr0's exception u1 */
#define SSR_A0_ELPR5 0x0f45 /* acr0's exception u2 */
#define SSR_A0_ELPR6 0x0f46 /* acr0's exception u3 */
#define SSR_A0_ELPR7 0x0f47 /* acr0's exception u4 */
#define SSR_A0_EBARG0 0x0f40 /* acr0 packed EBARG control word */
#define SSR_A0_EBARG_BPC_CUR 0x0f41 /* acr0 current block start PC */
#define SSR_A0_EBARG_BPC_TGT 0x0f42 /* acr0 next-block target PC */
#define SSR_A0_EBARG_TPC 0x0f43 /* acr0 body resume PC */
#define SSR_A0_EBARG_LRA 0x0f44 /* acr0 local return address */
#define SSR_A0_EBARG_TQ0 0x0f45 /* acr0 T-hand queue entry 0 */
#define SSR_A0_EBARG_TQ1 0x0f46 /* acr0 T-hand queue entry 1 */
#define SSR_A0_EBARG_TQ2 0x0f47 /* acr0 T-hand queue entry 2 */
#define SSR_A0_EBARG_TQ3 0x0f48 /* acr0 T-hand queue entry 3 */
#define SSR_A0_EBARG_UQ0 0x0f49 /* acr0 U-hand queue entry 0 */
#define SSR_A0_EBARG_UQ1 0x0f4a /* acr0 U-hand queue entry 1 */
#define SSR_A0_EBARG_UQ2 0x0f4b /* acr0 U-hand queue entry 2 */
#define SSR_A0_EBARG_UQ3 0x0f4c /* acr0 U-hand queue entry 3 */
#define SSR_A0_EBARG_LB 0x0f4d /* acr0 packed LB0..LB2 */
#define SSR_A0_EBARG_LC 0x0f4e /* acr0 packed LC0..LC2 */
#define SSR_A0_EBARG_EXTCTX_PTR 0x0f4f /* acr0 extended context pointer */
#define SSR_A0_EBARG_EXTCTX_META 0x0f50 /* acr0 extended context metadata */
#define SSR_A0_EBARG_TPLFLAGS 0x0f51 /* acr0 template replay flags */
/* Legacy aliases retained for bring-up compatibility. */
#define SSR_A0_ELPR0 SSR_A0_EBARG0
#define SSR_A0_ELPR1 SSR_A0_EBARG_BPC_CUR
#define SSR_A0_ELPR2 SSR_A0_EBARG_BPC_TGT
#define SSR_A0_ELPR3 SSR_A0_EBARG_TPC
#define SSR_A0_ELPR4 SSR_A0_EBARG_LRA
#define SSR_A0_ELPR5 SSR_A0_EBARG_TQ0
#define SSR_A0_ELPR6 SSR_A0_EBARG_TQ1
#define SSR_A0_ELPR7 SSR_A0_EBARG_TQ2


#define SSR_ACR_SIZE 0x1000
Expand All @@ -219,16 +238,50 @@
#define SSR_A1_TIMER_TIMECMP 0x1f21 /* acr1's timer configuration register */

#define SSR_A1_XBINFO 0x1f30 /* acr0's XB base register */
#define SSR_A1_ACR_PARAM 0x1f30 /* acr0's LxLc argument register */

#define SSR_A1_ELPR0 0x1f40 /* acr1's exception t1 */
#define SSR_A1_ELPR1 0x1f41 /* acr1's exception t2 */
#define SSR_A1_ELPR2 0x1f42 /* acr1's exception t3 */
#define SSR_A1_ELPR3 0x1f43 /* acr1's exception t4 */
#define SSR_A1_ELPR4 0x1f44 /* acr1's exception u1 */
#define SSR_A1_ELPR5 0x1f45 /* acr1's exception u2 */
#define SSR_A1_ELPR6 0x1f46 /* acr1's exception u3 */
#define SSR_A1_ELPR7 0x1f47 /* acr1's exception u4 */
#define SSR_A1_ACR_PARAM 0x1f31 /* acr1's LxLc argument register */

#define SSR_A1_EBARG0 0x1f40 /* acr1 packed EBARG control word */
#define SSR_A1_EBARG_BPC_CUR 0x1f41 /* acr1 current block start PC */
#define SSR_A1_EBARG_BPC_TGT 0x1f42 /* acr1 next-block target PC */
#define SSR_A1_EBARG_TPC 0x1f43 /* acr1 body resume PC */
#define SSR_A1_EBARG_LRA 0x1f44 /* acr1 local return address */
#define SSR_A1_EBARG_TQ0 0x1f45 /* acr1 T-hand queue entry 0 */
#define SSR_A1_EBARG_TQ1 0x1f46 /* acr1 T-hand queue entry 1 */
#define SSR_A1_EBARG_TQ2 0x1f47 /* acr1 T-hand queue entry 2 */
#define SSR_A1_EBARG_TQ3 0x1f48 /* acr1 T-hand queue entry 3 */
#define SSR_A1_EBARG_UQ0 0x1f49 /* acr1 U-hand queue entry 0 */
#define SSR_A1_EBARG_UQ1 0x1f4a /* acr1 U-hand queue entry 1 */
#define SSR_A1_EBARG_UQ2 0x1f4b /* acr1 U-hand queue entry 2 */
#define SSR_A1_EBARG_UQ3 0x1f4c /* acr1 U-hand queue entry 3 */
#define SSR_A1_EBARG_LB 0x1f4d /* acr1 packed LB0..LB2 */
#define SSR_A1_EBARG_LC 0x1f4e /* acr1 packed LC0..LC2 */
#define SSR_A1_EBARG_EXTCTX_PTR 0x1f4f /* acr1 extended context pointer */
#define SSR_A1_EBARG_EXTCTX_META 0x1f50 /* acr1 extended context metadata */
#define SSR_A1_EBARG_TPLFLAGS 0x1f51 /* acr1 template replay flags */
/* Hidden EBSTATE extension slots used by QEMU/Linux task-switch save/restore. */
#define SSR_A1_EBSTATE_EXT0 0x1f52
#define SSR_A1_EBSTATE_EXT1 0x1f53
#define SSR_A1_EBSTATE_EXT2 0x1f54
#define SSR_A1_EBSTATE_EXT3 0x1f55
#define SSR_A1_EBSTATE_EXT4 0x1f56
#define SSR_A1_EBSTATE_EXT5 0x1f57
#define SSR_A1_EBSTATE_EXT6 0x1f58
#define SSR_A1_EBSTATE_EXT7 0x1f59
#define SSR_A1_EBSTATE_EXT8 0x1f5a
#define SSR_A1_EBSTATE_EXT9 0x1f5b
#define SSR_A1_EBSTATE_EXT10 0x1f5c
#define SSR_A1_EBSTATE_EXT11 0x1f5d
#define SSR_A1_EBSTATE_EXT12 0x1f5e
#define SSR_A1_EBSTATE_EXT13 0x1f5f
/* Legacy aliases retained for bring-up compatibility. */
#define SSR_A1_ELPR0 SSR_A1_EBARG0
#define SSR_A1_ELPR1 SSR_A1_EBARG_BPC_CUR
#define SSR_A1_ELPR2 SSR_A1_EBARG_BPC_TGT
#define SSR_A1_ELPR3 SSR_A1_EBARG_TPC
#define SSR_A1_ELPR4 SSR_A1_EBARG_LRA
#define SSR_A1_ELPR5 SSR_A1_EBARG_TQ0
#define SSR_A1_ELPR6 SSR_A1_EBARG_TQ1
#define SSR_A1_ELPR7 SSR_A1_EBARG_TQ2


#define SSR_ECSTATE SSR_A1_ECSTATE /* acr1's exception store state */
Expand Down
Loading