Skip to content

Commit 4478688

Browse files
committed
Merge branch 'parisc-4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc updates from Helge Deller: "Lots of small fixes and enhancements, most noteably: - Many TLB and cache flush optimizations (Dave) - Fixed HPMC/crash handler on 64-bit kernel (Dave and myself) - Added alternative infrastructre. The kernel now live-patches itself for various situations, e.g. replace SMP code when running on one CPU only or drop cache flushes when system has no cache installed. - vmlinuz now contains a full copy of the compressed vmlinux file. This simplifies debugging the currently booted kernel. - Unused driver removal (Christoph) - Reduced warnings of Dino PCI bridge when running in qemu - Removed gcc version check (Masahiro)" * 'parisc-4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: (23 commits) parisc: Retrieve and display the PDC PAT capabilities parisc: Optimze cache flush algorithms parisc: Remove pte_inserted define parisc: Add PDC PAT cell_info() and pd_get_pdc_revisions() functions parisc: Drop two instructions from pte lookup code parisc: Use zdep for shlw macro on PA1.1 and PA2.0 parisc: Add alternative coding infrastructure parisc: Include compressed vmlinux file in vmlinuz boot kernel extract-vmlinux: Check for uncompressed image as fallback parisc: Fix address in HPMC IVA parisc: Fix exported address of os_hpmc handler parisc: Fix map_pages() to not overwrite existing pte entries parisc: Purge TLB entries after updating page table entry and set page accessed flag in TLB handler parisc: Release spinlocks using ordered store parisc: Ratelimit dino stuck interrupt warnings parisc: dino: Utilize DINO_MASK_IRQ() macro parisc: Clean up crash header output parisc: Add SYSTEM_INFO and REGISTER TOC PAT functions parisc: Remove PTE load and fault check from L2_ptep macro parisc: Reorder TLB flush timing calculation ...
2 parents 07171da + e543b3a commit 4478688

32 files changed

+721
-414
lines changed

arch/parisc/Makefile

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,3 @@ define archhelp
156156
@echo ' copy to $$(INSTALL_PATH)'
157157
@echo ' zinstall - Install compressed vmlinuz kernel'
158158
endef
159-
160-
# we require gcc 3.3 or above to compile the kernel
161-
archprepare: checkbin
162-
checkbin:
163-
@if test "$(cc-version)" -lt "0303"; then \
164-
echo -n "Sorry, GCC v3.3 or above is required to build " ; \
165-
echo "the kernel." ; \
166-
false ; \
167-
fi

arch/parisc/boot/compressed/Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@ targets += misc.o piggy.o sizes.h head.o real2.o firmware.o
1414

1515
KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER
1616
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
17-
KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks
17+
KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks -fno-builtin-printf
1818
KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os
1919
ifndef CONFIG_64BIT
2020
KBUILD_CFLAGS += -mfast-indirect-calls
2121
endif
2222

2323
OBJECTS += $(obj)/head.o $(obj)/real2.o $(obj)/firmware.o $(obj)/misc.o $(obj)/piggy.o
2424

25-
# LDFLAGS_vmlinux := -X --whole-archive -e startup -T
2625
LDFLAGS_vmlinux := -X -e startup --as-needed -T
2726
$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(LIBGCC)
2827
$(call if_changed,ld)
@@ -55,7 +54,6 @@ $(obj)/misc.o: $(obj)/sizes.h
5554
CPPFLAGS_vmlinux.lds += -I$(objtree)/$(obj) -DBOOTLOADER
5655
$(obj)/vmlinux.lds: $(obj)/sizes.h
5756

58-
OBJCOPYFLAGS_vmlinux.bin := -O binary -R .comment -S
5957
$(obj)/vmlinux.bin: vmlinux
6058
$(call if_changed,objcopy)
6159

arch/parisc/boot/compressed/misc.c

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <linux/uaccess.h>
8+
#include <linux/elf.h>
89
#include <asm/unaligned.h>
910
#include <asm/page.h>
1011
#include "sizes.h"
@@ -227,41 +228,92 @@ static void flush_data_cache(char *start, unsigned long length)
227228
asm ("sync");
228229
}
229230

231+
static void parse_elf(void *output)
232+
{
233+
#ifdef CONFIG_64BIT
234+
Elf64_Ehdr ehdr;
235+
Elf64_Phdr *phdrs, *phdr;
236+
#else
237+
Elf32_Ehdr ehdr;
238+
Elf32_Phdr *phdrs, *phdr;
239+
#endif
240+
void *dest;
241+
int i;
242+
243+
memcpy(&ehdr, output, sizeof(ehdr));
244+
if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
245+
ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
246+
ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
247+
ehdr.e_ident[EI_MAG3] != ELFMAG3) {
248+
error("Kernel is not a valid ELF file");
249+
return;
250+
}
251+
252+
#ifdef DEBUG
253+
printf("Parsing ELF... ");
254+
#endif
255+
256+
phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
257+
if (!phdrs)
258+
error("Failed to allocate space for phdrs");
259+
260+
memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);
261+
262+
for (i = 0; i < ehdr.e_phnum; i++) {
263+
phdr = &phdrs[i];
264+
265+
switch (phdr->p_type) {
266+
case PT_LOAD:
267+
dest = (void *)((unsigned long) phdr->p_paddr &
268+
(__PAGE_OFFSET_DEFAULT-1));
269+
memmove(dest, output + phdr->p_offset, phdr->p_filesz);
270+
break;
271+
default:
272+
break;
273+
}
274+
}
275+
276+
free(phdrs);
277+
}
278+
230279
unsigned long decompress_kernel(unsigned int started_wide,
231280
unsigned int command_line,
232281
const unsigned int rd_start,
233282
const unsigned int rd_end)
234283
{
235284
char *output;
236-
unsigned long len, len_all;
285+
unsigned long vmlinux_addr, vmlinux_len;
286+
unsigned long kernel_addr, kernel_len;
237287

238288
#ifdef CONFIG_64BIT
239289
parisc_narrow_firmware = 0;
240290
#endif
241291

242292
set_firmware_width_unlocked();
243293

244-
putchar('U'); /* if you get this p and no more, string storage */
294+
putchar('D'); /* if you get this D and no more, string storage */
245295
/* in $GLOBAL$ is wrong or %dp is wrong */
246-
puts("ncompressing ...\n");
247-
248-
output = (char *) KERNEL_BINARY_TEXT_START;
249-
len_all = __pa(SZ_end) - __pa(SZparisc_kernel_start);
296+
puts("ecompressing Linux... ");
250297

251-
if ((unsigned long) &_startcode_end > (unsigned long) output)
298+
/* where the final bits are stored */
299+
kernel_addr = KERNEL_BINARY_TEXT_START;
300+
kernel_len = __pa(SZ_end) - __pa(SZparisc_kernel_start);
301+
if ((unsigned long) &_startcode_end > kernel_addr)
252302
error("Bootcode overlaps kernel code");
253303

254-
len = get_unaligned_le32(&output_len);
255-
if (len > len_all)
256-
error("Output len too big.");
257-
else
258-
memset(&output[len], 0, len_all - len);
304+
/*
305+
* Calculate addr to where the vmlinux ELF file shall be decompressed.
306+
* Assembly code in head.S positioned the stack directly behind bss, so
307+
* leave 2 MB for the stack.
308+
*/
309+
vmlinux_addr = (unsigned long) &_ebss + 2*1024*1024;
310+
vmlinux_len = get_unaligned_le32(&output_len);
311+
output = (char *) vmlinux_addr;
259312

260313
/*
261314
* Initialize free_mem_ptr and free_mem_end_ptr.
262315
*/
263-
free_mem_ptr = (unsigned long) &_ebss;
264-
free_mem_ptr += 2*1024*1024; /* leave 2 MB for stack */
316+
free_mem_ptr = vmlinux_addr + vmlinux_len;
265317

266318
/* Limit memory for bootoader to 1GB */
267319
#define ARTIFICIAL_LIMIT (1*1024*1024*1024)
@@ -275,7 +327,11 @@ unsigned long decompress_kernel(unsigned int started_wide,
275327
free_mem_end_ptr = rd_start;
276328
#endif
277329

330+
if (free_mem_ptr >= free_mem_end_ptr)
331+
error("Kernel too big for machine.");
332+
278333
#ifdef DEBUG
334+
printf("\n");
279335
printf("startcode_end = %x\n", &_startcode_end);
280336
printf("commandline = %x\n", command_line);
281337
printf("rd_start = %x\n", rd_start);
@@ -287,16 +343,19 @@ unsigned long decompress_kernel(unsigned int started_wide,
287343
printf("input_data = %x\n", input_data);
288344
printf("input_len = %x\n", input_len);
289345
printf("output = %x\n", output);
290-
printf("output_len = %x\n", len);
291-
printf("output_max = %x\n", len_all);
346+
printf("output_len = %x\n", vmlinux_len);
347+
printf("kernel_addr = %x\n", kernel_addr);
348+
printf("kernel_len = %x\n", kernel_len);
292349
#endif
293350

294351
__decompress(input_data, input_len, NULL, NULL,
295352
output, 0, NULL, error);
353+
parse_elf(output);
296354

297-
flush_data_cache(output, len);
355+
output = (char *) kernel_addr;
356+
flush_data_cache(output, kernel_len);
298357

299-
printf("Booting kernel ...\n\n");
358+
printf("done.\nBooting the kernel.\n");
300359

301360
return (unsigned long) output;
302361
}

arch/parisc/boot/compressed/vmlinux.lds.S

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ SECTIONS
4242
#endif
4343
_startcode_end = .;
4444

45+
/* vmlinux.bin.gz is here */
46+
. = ALIGN(8);
47+
.rodata.compressed : {
48+
*(.rodata.compressed)
49+
}
50+
4551
/* bootloader code and data starts behind area of extracted kernel */
4652
. = (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START);
4753

@@ -68,10 +74,6 @@ SECTIONS
6874
_erodata = . ;
6975
}
7076
. = ALIGN(8);
71-
.rodata.compressed : {
72-
*(.rodata.compressed)
73-
}
74-
. = ALIGN(8);
7577
.bss : {
7678
_bss = . ;
7779
*(.bss)

arch/parisc/include/asm/alternative.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_PARISC_ALTERNATIVE_H
3+
#define __ASM_PARISC_ALTERNATIVE_H
4+
5+
#define ALT_COND_NO_SMP 0x01 /* when running UP instead of SMP */
6+
#define ALT_COND_NO_DCACHE 0x02 /* if system has no d-cache */
7+
#define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */
8+
#define ALT_COND_NO_SPLIT_TLB 0x08 /* if split_tlb == 0 */
9+
#define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */
10+
11+
#define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */
12+
#define INSN_NOP 0x08000240 /* nop */
13+
14+
#ifndef __ASSEMBLY__
15+
16+
#include <linux/init.h>
17+
#include <linux/types.h>
18+
#include <linux/stddef.h>
19+
#include <linux/stringify.h>
20+
21+
struct alt_instr {
22+
s32 orig_offset; /* offset to original instructions */
23+
u32 len; /* end of original instructions */
24+
u32 cond; /* see ALT_COND_XXX */
25+
u32 replacement; /* replacement instruction or code */
26+
};
27+
28+
void set_kernel_text_rw(int enable_read_write);
29+
30+
/* Alternative SMP implementation. */
31+
#define ALTERNATIVE(cond, replacement) "!0:" \
32+
".section .altinstructions, \"aw\" !" \
33+
".word (0b-4-.), 1, " __stringify(cond) "," \
34+
__stringify(replacement) " !" \
35+
".previous"
36+
37+
#else
38+
39+
#define ALTERNATIVE(from, to, cond, replacement)\
40+
.section .altinstructions, "aw" ! \
41+
.word (from - .), (to - from)/4 ! \
42+
.word cond, replacement ! \
43+
.previous
44+
45+
#endif /* __ASSEMBLY__ */
46+
47+
#endif /* __ASM_PARISC_ALTERNATIVE_H */

arch/parisc/include/asm/assembly.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,8 @@
129129
.macro debug value
130130
.endm
131131

132-
133-
/* Shift Left - note the r and t can NOT be the same! */
134-
.macro shl r, sa, t
135-
dep,z \r, 31-(\sa), 32-(\sa), \t
136-
.endm
137-
138-
/* The PA 2.0 shift left */
139132
.macro shlw r, sa, t
140-
depw,z \r, 31-(\sa), 32-(\sa), \t
133+
zdep \r, 31-(\sa), 32-(\sa), \t
141134
.endm
142135

143136
/* And the PA 2.0W shift left */

arch/parisc/include/asm/cache.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef __ARCH_PARISC_CACHE_H
77
#define __ARCH_PARISC_CACHE_H
88

9+
#include <asm/alternative.h>
910

1011
/*
1112
* PA 2.0 processors have 64 and 128-byte L2 cachelines; PA 1.1 processors
@@ -41,9 +42,24 @@ extern int icache_stride;
4142
extern struct pdc_cache_info cache_info;
4243
void parisc_setup_cache_timing(void);
4344

44-
#define pdtlb(addr) asm volatile("pdtlb 0(%%sr1,%0)" : : "r" (addr));
45-
#define pitlb(addr) asm volatile("pitlb 0(%%sr1,%0)" : : "r" (addr));
46-
#define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" : : "r" (addr));
45+
#define pdtlb(addr) asm volatile("pdtlb 0(%%sr1,%0)" \
46+
ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \
47+
: : "r" (addr))
48+
#define pitlb(addr) asm volatile("pitlb 0(%%sr1,%0)" \
49+
ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \
50+
ALTERNATIVE(ALT_COND_NO_SPLIT_TLB, INSN_NOP) \
51+
: : "r" (addr))
52+
#define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" \
53+
ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \
54+
: : "r" (addr))
55+
56+
#define asm_io_fdc(addr) asm volatile("fdc %%r0(%0)" \
57+
ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \
58+
ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) \
59+
: : "r" (addr))
60+
#define asm_io_sync() asm volatile("sync" \
61+
ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \
62+
ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :: )
4763

4864
#endif /* ! __ASSEMBLY__ */
4965

arch/parisc/include/asm/page.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,16 @@ extern int npmem_ranges;
117117
/* This governs the relationship between virtual and physical addresses.
118118
* If you alter it, make sure to take care of our various fixed mapping
119119
* segments in fixmap.h */
120-
#if defined(BOOTLOADER)
121-
#define __PAGE_OFFSET (0) /* bootloader uses physical addresses */
122-
#else
123120
#ifdef CONFIG_64BIT
124-
#define __PAGE_OFFSET (0x40000000) /* 1GB */
121+
#define __PAGE_OFFSET_DEFAULT (0x40000000) /* 1GB */
125122
#else
126-
#define __PAGE_OFFSET (0x10000000) /* 256MB */
123+
#define __PAGE_OFFSET_DEFAULT (0x10000000) /* 256MB */
127124
#endif
125+
126+
#if defined(BOOTLOADER)
127+
#define __PAGE_OFFSET (0) /* bootloader uses physical addresses */
128+
#else
129+
#define __PAGE_OFFSET __PAGE_OFFSET_DEFAULT
128130
#endif /* BOOTLOADER */
129131

130132
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)

arch/parisc/include/asm/pdc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern int parisc_narrow_firmware;
1111
extern int pdc_type;
1212
extern unsigned long parisc_cell_num; /* cell number the CPU runs on (PAT) */
1313
extern unsigned long parisc_cell_loc; /* cell location of CPU (PAT) */
14+
extern unsigned long parisc_pat_pdc_cap; /* PDC capabilities (PAT) */
1415

1516
/* Values for pdc_type */
1617
#define PDC_TYPE_ILLEGAL -1

0 commit comments

Comments
 (0)