Skip to content

Commit a361474

Browse files
committed
Merge tag 'loongarch-fixes-7.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch fixes from Huacai Chen: "Fix missing NULL checks for kstrdup(), workaround LS2K/LS7A GPU DMA hang bug, emit GNU_EH_FRAME for vDSO correctly, and fix some KVM-related bugs" * tag 'loongarch-fixes-7.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: LoongArch: KVM: Fix base address calculation in kvm_eiointc_regs_access() LoongArch: KVM: Handle the case that EIOINTC's coremap is empty LoongArch: KVM: Make kvm_get_vcpu_by_cpuid() more robust LoongArch: vDSO: Emit GNU_EH_FRAME correctly LoongArch: Workaround LS2K/LS7A GPU DMA hang bug LoongArch: Fix missing NULL checks for kstrdup()
2 parents 196ef74 + 6bcfb7f commit a361474

10 files changed

Lines changed: 147 additions & 22 deletions

File tree

arch/loongarch/include/asm/linkage.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,40 @@
4141
.cfi_endproc; \
4242
SYM_END(name, SYM_T_NONE)
4343

44+
/*
45+
* This is for the signal handler trampoline, which is used as the return
46+
* address of the signal handlers in userspace instead of called normally.
47+
* The long standing libgcc bug https://gcc.gnu.org/PR124050 requires a
48+
* nop between .cfi_startproc and the actual address of the trampoline, so
49+
* we cannot simply use SYM_FUNC_START.
50+
*
51+
* This wrapper also contains all the .cfi_* directives for recovering
52+
* the content of the GPRs and the "return address" (where the rt_sigreturn
53+
* syscall will jump to), assuming there is a struct rt_sigframe (where
54+
* a struct sigcontext containing those information we need to recover) at
55+
* $sp. The "DWARF for the LoongArch(TM) Architecture" manual states
56+
* column 0 is for $zero, but it does not make too much sense to
57+
* save/restore the hardware zero register. Repurpose this column here
58+
* for the return address (here it's not the content of $ra we cannot use
59+
* the default column 3).
60+
*/
61+
#define SYM_SIGFUNC_START(name) \
62+
.cfi_startproc; \
63+
.cfi_signal_frame; \
64+
.cfi_def_cfa 3, RT_SIGFRAME_SC; \
65+
.cfi_return_column 0; \
66+
.cfi_offset 0, SC_PC; \
67+
\
68+
.irp num, 1, 2, 3, 4, 5, 6, 7, 8, \
69+
9, 10, 11, 12, 13, 14, 15, 16, \
70+
17, 18, 19, 20, 21, 22, 23, 24, \
71+
25, 26, 27, 28, 29, 30, 31; \
72+
.cfi_offset \num, SC_REGS + \num * SZREG; \
73+
.endr; \
74+
\
75+
nop; \
76+
SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
77+
78+
#define SYM_SIGFUNC_END(name) SYM_FUNC_END(name)
79+
4480
#endif
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
3+
#include <asm/siginfo.h>
4+
#include <asm/ucontext.h>
5+
6+
struct rt_sigframe {
7+
struct siginfo rs_info;
8+
struct ucontext rs_uctx;
9+
};

arch/loongarch/kernel/asm-offsets.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <asm/ptrace.h>
1717
#include <asm/processor.h>
1818
#include <asm/ftrace.h>
19+
#include <asm/sigframe.h>
1920
#include <vdso/datapage.h>
2021

2122
static void __used output_ptreg_defines(void)
@@ -220,6 +221,7 @@ static void __used output_sc_defines(void)
220221
COMMENT("Linux sigcontext offsets.");
221222
OFFSET(SC_REGS, sigcontext, sc_regs);
222223
OFFSET(SC_PC, sigcontext, sc_pc);
224+
OFFSET(RT_SIGFRAME_SC, rt_sigframe, rs_uctx.uc_mcontext);
223225
BLANK();
224226
}
225227

arch/loongarch/kernel/env.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,15 @@ static int __init init_cpu_fullname(void)
4242
int cpu, ret;
4343
char *cpuname;
4444
const char *model;
45-
struct device_node *root;
4645

4746
/* Parsing cpuname from DTS model property */
48-
root = of_find_node_by_path("/");
49-
ret = of_property_read_string(root, "model", &model);
47+
ret = of_property_read_string(of_root, "model", &model);
5048
if (ret == 0) {
5149
cpuname = kstrdup(model, GFP_KERNEL);
50+
if (!cpuname)
51+
return -ENOMEM;
5252
loongson_sysconf.cpuname = strsep(&cpuname, " ");
5353
}
54-
of_node_put(root);
5554

5655
if (loongson_sysconf.cpuname && !strncmp(loongson_sysconf.cpuname, "Loongson", 8)) {
5756
for (cpu = 0; cpu < NR_CPUS; cpu++)

arch/loongarch/kernel/signal.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <asm/cpu-features.h>
3636
#include <asm/fpu.h>
3737
#include <asm/lbt.h>
38+
#include <asm/sigframe.h>
3839
#include <asm/ucontext.h>
3940
#include <asm/vdso.h>
4041

@@ -51,11 +52,6 @@
5152
#define lock_lbt_owner() ({ preempt_disable(); pagefault_disable(); })
5253
#define unlock_lbt_owner() ({ pagefault_enable(); preempt_enable(); })
5354

54-
struct rt_sigframe {
55-
struct siginfo rs_info;
56-
struct ucontext rs_uctx;
57-
};
58-
5955
struct _ctx_layout {
6056
struct sctx_info *addr;
6157
unsigned int size;

arch/loongarch/kvm/intc/eiointc.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s,
8383

8484
if (!(s->status & BIT(EIOINTC_ENABLE_CPU_ENCODE))) {
8585
cpuid = ffs(cpuid) - 1;
86-
cpuid = (cpuid >= 4) ? 0 : cpuid;
86+
cpuid = ((cpuid < 0) || (cpuid >= 4)) ? 0 : cpuid;
8787
}
8888

8989
vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid);
@@ -472,34 +472,34 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
472472
switch (addr) {
473473
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
474474
offset = (addr - EIOINTC_NODETYPE_START) / 4;
475-
p = s->nodetype + offset * 4;
475+
p = (void *)s->nodetype + offset * 4;
476476
break;
477477
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
478478
offset = (addr - EIOINTC_IPMAP_START) / 4;
479-
p = &s->ipmap + offset * 4;
479+
p = (void *)&s->ipmap + offset * 4;
480480
break;
481481
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
482482
offset = (addr - EIOINTC_ENABLE_START) / 4;
483-
p = s->enable + offset * 4;
483+
p = (void *)s->enable + offset * 4;
484484
break;
485485
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
486486
offset = (addr - EIOINTC_BOUNCE_START) / 4;
487-
p = s->bounce + offset * 4;
487+
p = (void *)s->bounce + offset * 4;
488488
break;
489489
case EIOINTC_ISR_START ... EIOINTC_ISR_END:
490490
offset = (addr - EIOINTC_ISR_START) / 4;
491-
p = s->isr + offset * 4;
491+
p = (void *)s->isr + offset * 4;
492492
break;
493493
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
494494
if (cpu >= s->num_cpu)
495495
return -EINVAL;
496496

497497
offset = (addr - EIOINTC_COREISR_START) / 4;
498-
p = s->coreisr[cpu] + offset * 4;
498+
p = (void *)s->coreisr[cpu] + offset * 4;
499499
break;
500500
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
501501
offset = (addr - EIOINTC_COREMAP_START) / 4;
502-
p = s->coremap + offset * 4;
502+
p = (void *)s->coremap + offset * 4;
503503
break;
504504
default:
505505
kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr);

arch/loongarch/kvm/vcpu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,9 @@ struct kvm_vcpu *kvm_get_vcpu_by_cpuid(struct kvm *kvm, int cpuid)
588588
{
589589
struct kvm_phyid_map *map;
590590

591+
if (cpuid < 0)
592+
return NULL;
593+
591594
if (cpuid >= KVM_MAX_PHYID)
592595
return NULL;
593596

arch/loongarch/pci/pci.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,21 @@
55
#include <linux/kernel.h>
66
#include <linux/init.h>
77
#include <linux/acpi.h>
8+
#include <linux/delay.h>
89
#include <linux/types.h>
910
#include <linux/pci.h>
1011
#include <linux/vgaarb.h>
12+
#include <linux/io-64-nonatomic-lo-hi.h>
1113
#include <asm/cacheflush.h>
1214
#include <asm/loongson.h>
1315

1416
#define PCI_DEVICE_ID_LOONGSON_HOST 0x7a00
1517
#define PCI_DEVICE_ID_LOONGSON_DC1 0x7a06
1618
#define PCI_DEVICE_ID_LOONGSON_DC2 0x7a36
1719
#define PCI_DEVICE_ID_LOONGSON_DC3 0x7a46
20+
#define PCI_DEVICE_ID_LOONGSON_GPU1 0x7a15
21+
#define PCI_DEVICE_ID_LOONGSON_GPU2 0x7a25
22+
#define PCI_DEVICE_ID_LOONGSON_GPU3 0x7a35
1823

1924
int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
2025
int reg, int len, u32 *val)
@@ -99,3 +104,78 @@ static void pci_fixup_vgadev(struct pci_dev *pdev)
99104
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC1, pci_fixup_vgadev);
100105
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC2, pci_fixup_vgadev);
101106
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC3, pci_fixup_vgadev);
107+
108+
#define CRTC_NUM_MAX 2
109+
#define CRTC_OUTPUT_ENABLE 0x100
110+
111+
static void loongson_gpu_fixup_dma_hang(struct pci_dev *pdev, bool on)
112+
{
113+
u32 i, val, count, crtc_offset, device;
114+
void __iomem *crtc_reg, *base, *regbase;
115+
static u32 crtc_status[CRTC_NUM_MAX] = { 0 };
116+
117+
base = pdev->bus->ops->map_bus(pdev->bus, pdev->devfn + 1, 0);
118+
device = readw(base + PCI_DEVICE_ID);
119+
120+
regbase = ioremap(readq(base + PCI_BASE_ADDRESS_0) & ~0xffull, SZ_64K);
121+
if (!regbase) {
122+
pci_err(pdev, "Failed to ioremap()\n");
123+
return;
124+
}
125+
126+
switch (device) {
127+
case PCI_DEVICE_ID_LOONGSON_DC2:
128+
crtc_reg = regbase + 0x1240;
129+
crtc_offset = 0x10;
130+
break;
131+
case PCI_DEVICE_ID_LOONGSON_DC3:
132+
crtc_reg = regbase;
133+
crtc_offset = 0x400;
134+
break;
135+
}
136+
137+
for (i = 0; i < CRTC_NUM_MAX; i++, crtc_reg += crtc_offset) {
138+
val = readl(crtc_reg);
139+
140+
if (!on)
141+
crtc_status[i] = val;
142+
143+
/* No need to fixup if the status is off at startup. */
144+
if (!(crtc_status[i] & CRTC_OUTPUT_ENABLE))
145+
continue;
146+
147+
if (on)
148+
val |= CRTC_OUTPUT_ENABLE;
149+
else
150+
val &= ~CRTC_OUTPUT_ENABLE;
151+
152+
mb();
153+
writel(val, crtc_reg);
154+
155+
for (count = 0; count < 40; count++) {
156+
val = readl(crtc_reg) & CRTC_OUTPUT_ENABLE;
157+
if ((on && val) || (!on && !val))
158+
break;
159+
udelay(1000);
160+
}
161+
162+
pci_info(pdev, "DMA hang fixup at reg[0x%lx]: 0x%x\n",
163+
(unsigned long)crtc_reg & 0xffff, readl(crtc_reg));
164+
}
165+
166+
iounmap(regbase);
167+
}
168+
169+
static void pci_fixup_dma_hang_early(struct pci_dev *pdev)
170+
{
171+
loongson_gpu_fixup_dma_hang(pdev, false);
172+
}
173+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU2, pci_fixup_dma_hang_early);
174+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU3, pci_fixup_dma_hang_early);
175+
176+
static void pci_fixup_dma_hang_final(struct pci_dev *pdev)
177+
{
178+
loongson_gpu_fixup_dma_hang(pdev, true);
179+
}
180+
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU2, pci_fixup_dma_hang_final);
181+
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU3, pci_fixup_dma_hang_final);

arch/loongarch/vdso/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ cflags-vdso := $(ccflags-vdso) \
2626
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
2727
-std=gnu11 -fms-extensions -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \
2828
-fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
29-
$(call cc-option, -fno-asynchronous-unwind-tables) \
29+
$(call cc-option, -fasynchronous-unwind-tables) \
3030
$(call cc-option, -fno-stack-protector)
3131
aflags-vdso := $(ccflags-vdso) \
3232
-D__ASSEMBLY__ -Wa,-gdwarf-2
@@ -41,7 +41,7 @@ endif
4141

4242
# VDSO linker flags.
4343
ldflags-y := -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \
44-
$(filter -E%,$(KBUILD_CFLAGS)) -shared --build-id -T
44+
$(filter -E%,$(KBUILD_CFLAGS)) -shared --build-id --eh-frame-hdr -T
4545

4646
#
4747
# Shared build commands.

arch/loongarch/vdso/sigreturn.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212

1313
#include <asm/regdef.h>
1414
#include <asm/asm.h>
15+
#include <asm/asm-offsets.h>
1516

1617
.section .text
17-
.cfi_sections .debug_frame
1818

19-
SYM_FUNC_START(__vdso_rt_sigreturn)
19+
SYM_SIGFUNC_START(__vdso_rt_sigreturn)
2020

2121
li.w a7, __NR_rt_sigreturn
2222
syscall 0
2323

24-
SYM_FUNC_END(__vdso_rt_sigreturn)
24+
SYM_SIGFUNC_END(__vdso_rt_sigreturn)

0 commit comments

Comments
 (0)