Skip to content

Commit

Permalink
Merge branch 'parisc-4.20-1' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  ...
  • Loading branch information
torvalds committed Oct 23, 2018
2 parents 07171da + e543b3a commit 4478688
Show file tree
Hide file tree
Showing 32 changed files with 721 additions and 414 deletions.
9 changes: 0 additions & 9 deletions arch/parisc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,3 @@ define archhelp
@echo ' copy to $$(INSTALL_PATH)'
@echo ' zinstall - Install compressed vmlinuz kernel'
endef

# we require gcc 3.3 or above to compile the kernel
archprepare: checkbin
checkbin:
@if test "$(cc-version)" -lt "0303"; then \
echo -n "Sorry, GCC v3.3 or above is required to build " ; \
echo "the kernel." ; \
false ; \
fi
4 changes: 1 addition & 3 deletions arch/parisc/boot/compressed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ targets += misc.o piggy.o sizes.h head.o real2.o firmware.o

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

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

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

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

Expand Down
95 changes: 77 additions & 18 deletions arch/parisc/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <linux/uaccess.h>
#include <linux/elf.h>
#include <asm/unaligned.h>
#include <asm/page.h>
#include "sizes.h"
Expand Down Expand Up @@ -227,41 +228,92 @@ static void flush_data_cache(char *start, unsigned long length)
asm ("sync");
}

static void parse_elf(void *output)
{
#ifdef CONFIG_64BIT
Elf64_Ehdr ehdr;
Elf64_Phdr *phdrs, *phdr;
#else
Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs, *phdr;
#endif
void *dest;
int i;

memcpy(&ehdr, output, sizeof(ehdr));
if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
ehdr.e_ident[EI_MAG3] != ELFMAG3) {
error("Kernel is not a valid ELF file");
return;
}

#ifdef DEBUG
printf("Parsing ELF... ");
#endif

phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
if (!phdrs)
error("Failed to allocate space for phdrs");

memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);

for (i = 0; i < ehdr.e_phnum; i++) {
phdr = &phdrs[i];

switch (phdr->p_type) {
case PT_LOAD:
dest = (void *)((unsigned long) phdr->p_paddr &
(__PAGE_OFFSET_DEFAULT-1));
memmove(dest, output + phdr->p_offset, phdr->p_filesz);
break;
default:
break;
}
}

free(phdrs);
}

unsigned long decompress_kernel(unsigned int started_wide,
unsigned int command_line,
const unsigned int rd_start,
const unsigned int rd_end)
{
char *output;
unsigned long len, len_all;
unsigned long vmlinux_addr, vmlinux_len;
unsigned long kernel_addr, kernel_len;

#ifdef CONFIG_64BIT
parisc_narrow_firmware = 0;
#endif

set_firmware_width_unlocked();

putchar('U'); /* if you get this p and no more, string storage */
putchar('D'); /* if you get this D and no more, string storage */
/* in $GLOBAL$ is wrong or %dp is wrong */
puts("ncompressing ...\n");

output = (char *) KERNEL_BINARY_TEXT_START;
len_all = __pa(SZ_end) - __pa(SZparisc_kernel_start);
puts("ecompressing Linux... ");

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

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

/*
* Initialize free_mem_ptr and free_mem_end_ptr.
*/
free_mem_ptr = (unsigned long) &_ebss;
free_mem_ptr += 2*1024*1024; /* leave 2 MB for stack */
free_mem_ptr = vmlinux_addr + vmlinux_len;

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

if (free_mem_ptr >= free_mem_end_ptr)
error("Kernel too big for machine.");

#ifdef DEBUG
printf("\n");
printf("startcode_end = %x\n", &_startcode_end);
printf("commandline = %x\n", command_line);
printf("rd_start = %x\n", rd_start);
Expand All @@ -287,16 +343,19 @@ unsigned long decompress_kernel(unsigned int started_wide,
printf("input_data = %x\n", input_data);
printf("input_len = %x\n", input_len);
printf("output = %x\n", output);
printf("output_len = %x\n", len);
printf("output_max = %x\n", len_all);
printf("output_len = %x\n", vmlinux_len);
printf("kernel_addr = %x\n", kernel_addr);
printf("kernel_len = %x\n", kernel_len);
#endif

__decompress(input_data, input_len, NULL, NULL,
output, 0, NULL, error);
parse_elf(output);

flush_data_cache(output, len);
output = (char *) kernel_addr;
flush_data_cache(output, kernel_len);

printf("Booting kernel ...\n\n");
printf("done.\nBooting the kernel.\n");

return (unsigned long) output;
}
10 changes: 6 additions & 4 deletions arch/parisc/boot/compressed/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ SECTIONS
#endif
_startcode_end = .;

/* vmlinux.bin.gz is here */
. = ALIGN(8);
.rodata.compressed : {
*(.rodata.compressed)
}

/* bootloader code and data starts behind area of extracted kernel */
. = (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START);

Expand All @@ -68,10 +74,6 @@ SECTIONS
_erodata = . ;
}
. = ALIGN(8);
.rodata.compressed : {
*(.rodata.compressed)
}
. = ALIGN(8);
.bss : {
_bss = . ;
*(.bss)
Expand Down
47 changes: 47 additions & 0 deletions arch/parisc/include/asm/alternative.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_PARISC_ALTERNATIVE_H
#define __ASM_PARISC_ALTERNATIVE_H

#define ALT_COND_NO_SMP 0x01 /* when running UP instead of SMP */
#define ALT_COND_NO_DCACHE 0x02 /* if system has no d-cache */
#define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */
#define ALT_COND_NO_SPLIT_TLB 0x08 /* if split_tlb == 0 */
#define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */

#define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */
#define INSN_NOP 0x08000240 /* nop */

#ifndef __ASSEMBLY__

#include <linux/init.h>
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/stringify.h>

struct alt_instr {
s32 orig_offset; /* offset to original instructions */
u32 len; /* end of original instructions */
u32 cond; /* see ALT_COND_XXX */
u32 replacement; /* replacement instruction or code */
};

void set_kernel_text_rw(int enable_read_write);

/* Alternative SMP implementation. */
#define ALTERNATIVE(cond, replacement) "!0:" \
".section .altinstructions, \"aw\" !" \
".word (0b-4-.), 1, " __stringify(cond) "," \
__stringify(replacement) " !" \
".previous"

#else

#define ALTERNATIVE(from, to, cond, replacement)\
.section .altinstructions, "aw" ! \
.word (from - .), (to - from)/4 ! \
.word cond, replacement ! \
.previous

#endif /* __ASSEMBLY__ */

#endif /* __ASM_PARISC_ALTERNATIVE_H */
9 changes: 1 addition & 8 deletions arch/parisc/include/asm/assembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,8 @@
.macro debug value
.endm


/* Shift Left - note the r and t can NOT be the same! */
.macro shl r, sa, t
dep,z \r, 31-(\sa), 32-(\sa), \t
.endm

/* The PA 2.0 shift left */
.macro shlw r, sa, t
depw,z \r, 31-(\sa), 32-(\sa), \t
zdep \r, 31-(\sa), 32-(\sa), \t
.endm

/* And the PA 2.0W shift left */
Expand Down
22 changes: 19 additions & 3 deletions arch/parisc/include/asm/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef __ARCH_PARISC_CACHE_H
#define __ARCH_PARISC_CACHE_H

#include <asm/alternative.h>

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

#define pdtlb(addr) asm volatile("pdtlb 0(%%sr1,%0)" : : "r" (addr));
#define pitlb(addr) asm volatile("pitlb 0(%%sr1,%0)" : : "r" (addr));
#define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" : : "r" (addr));
#define pdtlb(addr) asm volatile("pdtlb 0(%%sr1,%0)" \
ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \
: : "r" (addr))
#define pitlb(addr) asm volatile("pitlb 0(%%sr1,%0)" \
ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \
ALTERNATIVE(ALT_COND_NO_SPLIT_TLB, INSN_NOP) \
: : "r" (addr))
#define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" \
ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \
: : "r" (addr))

#define asm_io_fdc(addr) asm volatile("fdc %%r0(%0)" \
ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \
ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) \
: : "r" (addr))
#define asm_io_sync() asm volatile("sync" \
ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \
ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :: )

#endif /* ! __ASSEMBLY__ */

Expand Down
12 changes: 7 additions & 5 deletions arch/parisc/include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,16 @@ extern int npmem_ranges;
/* This governs the relationship between virtual and physical addresses.
* If you alter it, make sure to take care of our various fixed mapping
* segments in fixmap.h */
#if defined(BOOTLOADER)
#define __PAGE_OFFSET (0) /* bootloader uses physical addresses */
#else
#ifdef CONFIG_64BIT
#define __PAGE_OFFSET (0x40000000) /* 1GB */
#define __PAGE_OFFSET_DEFAULT (0x40000000) /* 1GB */
#else
#define __PAGE_OFFSET (0x10000000) /* 256MB */
#define __PAGE_OFFSET_DEFAULT (0x10000000) /* 256MB */
#endif

#if defined(BOOTLOADER)
#define __PAGE_OFFSET (0) /* bootloader uses physical addresses */
#else
#define __PAGE_OFFSET __PAGE_OFFSET_DEFAULT
#endif /* BOOTLOADER */

#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
Expand Down
1 change: 1 addition & 0 deletions arch/parisc/include/asm/pdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern int parisc_narrow_firmware;
extern int pdc_type;
extern unsigned long parisc_cell_num; /* cell number the CPU runs on (PAT) */
extern unsigned long parisc_cell_loc; /* cell location of CPU (PAT) */
extern unsigned long parisc_pat_pdc_cap; /* PDC capabilities (PAT) */

/* Values for pdc_type */
#define PDC_TYPE_ILLEGAL -1
Expand Down
Loading

0 comments on commit 4478688

Please sign in to comment.