Commit f2e44139 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'parisc-for-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc updates from Helge Deller:
 "Fixes:

   - When we added basic vDSO support in kernel 5.18 we introduced a bug
     which prevented a mmap() of graphic card memory. This is because we
     used the DMB (data memory break trap bit) page flag as special-bit,
     but missed to clear that bit when loading the TLB.

   - Graphics card memory size was not correctly aligned

   - Spelling fixes (from Colin Ian King)

  Enhancements:

   - PDC console (which uses firmware calls) now rewritten as early
     console

   - Reduced size of alternative tables"

* tag 'parisc-for-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Fix spelling mistake "mis-match" -> "mismatch" in eisa driver
  parisc: Fix userspace graphics card breakage due to pgtable special bit
  parisc: fbdev/stifb: Align graphics memory size to 4MB
  parisc: Convert PDC console to an early console
  parisc: Reduce kernel size by packing alternative tables
parents ebdca8ec 34314cd6
......@@ -22,10 +22,10 @@
struct alt_instr {
s32 orig_offset; /* offset to original instructions */
s32 len; /* end of original instructions */
u32 cond; /* see ALT_COND_XXX */
s16 len; /* end of original instructions */
u16 cond; /* see ALT_COND_XXX */
u32 replacement; /* replacement instruction or code */
};
} __packed;
void set_kernel_text_rw(int enable_read_write);
void apply_alternatives_all(void);
......@@ -35,8 +35,9 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* Alternative SMP implementation. */
#define ALTERNATIVE(cond, replacement) "!0:" \
".section .altinstructions, \"aw\" !" \
".word (0b-4-.), 1, " __stringify(cond) "," \
__stringify(replacement) " !" \
".word (0b-4-.) !" \
".hword 1, " __stringify(cond) " !" \
".word " __stringify(replacement) " !" \
".previous"
#else
......@@ -44,15 +45,17 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* to replace one single instructions by a new instruction */
#define ALTERNATIVE(from, to, cond, replacement)\
.section .altinstructions, "aw" ! \
.word (from - .), (to - from)/4 ! \
.word cond, replacement ! \
.word (from - .) ! \
.hword (to - from)/4, cond ! \
.word replacement ! \
.previous
/* to replace multiple instructions by new code */
#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\
.section .altinstructions, "aw" ! \
.word (from - .), -num_instructions ! \
.word cond, (new_instr_ptr - .) ! \
.word (from - .) ! \
.hword -num_instructions, cond ! \
.word (new_instr_ptr - .) ! \
.previous
#endif /* __ASSEMBLY__ */
......
......@@ -19,9 +19,6 @@ extern unsigned long parisc_pat_pdc_cap; /* PDC capabilities (PAT) */
#define PDC_TYPE_SYSTEM_MAP 1 /* 32-bit, but supports PDC_SYSTEM_MAP */
#define PDC_TYPE_SNAKE 2 /* Doesn't support SYSTEM_MAP */
void pdc_console_init(void); /* in pdc_console.c */
void pdc_console_restart(void);
void setup_pdc(void); /* in inventory.c */
/* wrapper-functions from pdc.c */
......
......@@ -192,6 +192,11 @@ extern void __update_cache(pte_t pte);
#define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */
#define _PAGE_HPAGE_BIT 21 /* (0x400) Software: Huge Page */
#define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */
#ifdef CONFIG_HUGETLB_PAGE
#define _PAGE_SPECIAL_BIT _PAGE_DMB_BIT /* DMB feature is currently unused */
#else
#define _PAGE_SPECIAL_BIT _PAGE_HPAGE_BIT /* use unused HUGE PAGE bit */
#endif
/* N.B. The bits are defined in terms of a 32 bit word above, so the */
/* following macro is ok for both 32 and 64 bit. */
......@@ -219,7 +224,7 @@ extern void __update_cache(pte_t pte);
#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT))
#define _PAGE_HUGE (1 << xlate_pabit(_PAGE_HPAGE_BIT))
#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT))
#define _PAGE_SPECIAL (_PAGE_DMB)
#define _PAGE_SPECIAL (1 << xlate_pabit(_PAGE_SPECIAL_BIT))
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
......
......@@ -26,7 +26,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
struct alt_instr *entry;
int index = 0, applied = 0;
int num_cpus = num_online_cpus();
u32 cond_check;
u16 cond_check;
cond_check = ALT_COND_ALWAYS |
((num_cpus == 1) ? ALT_COND_NO_SMP : 0) |
......@@ -45,8 +45,9 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
for (entry = start; entry < end; entry++, index++) {
u32 *from, cond, replacement;
s32 len;
u32 *from, replacement;
u16 cond;
s16 len;
from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset);
len = entry->len;
......
......@@ -499,6 +499,10 @@
* Finally, _PAGE_READ goes in the top bit of PL1 (so we
* trigger an access rights trap in user space if the user
* tries to read an unreadable page */
#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT
/* need to drop DMB bit, as it's used as SPECIAL flag */
depi 0,_PAGE_SPECIAL_BIT,1,\pte
#endif
depd \pte,8,7,\prot
/* PAGE_USER indicates the page can be read with user privileges,
......@@ -529,6 +533,10 @@
* makes the tlb entry for the differently formatted pa11
* insertion instructions */
.macro make_insert_tlb_11 spc,pte,prot
#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT
/* need to drop DMB bit, as it's used as SPECIAL flag */
depi 0,_PAGE_SPECIAL_BIT,1,\pte
#endif
zdep \spc,30,15,\prot
dep \pte,8,7,\prot
extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PDC Console support - ie use firmware to dump text via boot console
* PDC early console support - use PDC firmware to dump text via boot console
*
* Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
* Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
* Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
* Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
* Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
* Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
* Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
* Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
* Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
* Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
* Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be>
* Copyright (C) 2001-2022 Helge Deller <deller@gmx.de>
*/
/*
* The PDC console is a simple console, which can be used for debugging
* boot related problems on HP PA-RISC machines. It is also useful when no
* other console works.
*
* This code uses the ROM (=PDC) based functions to read and write characters
* from and to PDC's boot path.
*/
/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
* On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
#define EARLY_BOOTUP_DEBUG
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <linux/kgdb.h>
#include <asm/page.h> /* for PAGE0 */
#include <asm/pdc.h> /* for iodc_call() proto and friends */
static DEFINE_SPINLOCK(pdc_console_lock);
static struct console pdc_cons;
static void pdc_console_write(struct console *co, const char *s, unsigned count)
{
......@@ -54,7 +26,8 @@ static void pdc_console_write(struct console *co, const char *s, unsigned count)
spin_unlock_irqrestore(&pdc_console_lock, flags);
}
int pdc_console_poll_key(struct console *co)
#ifdef CONFIG_KGDB
static int kgdb_pdc_read_char(void)
{
int c;
unsigned long flags;
......@@ -63,201 +36,40 @@ int pdc_console_poll_key(struct console *co)
c = pdc_iodc_getc();
spin_unlock_irqrestore(&pdc_console_lock, flags);
return c;
}
static int pdc_console_setup(struct console *co, char *options)
{
return 0;
}
#if defined(CONFIG_PDC_CONSOLE)
#include <linux/vt_kern.h>
#include <linux/tty_flip.h>
#define PDC_CONS_POLL_DELAY (30 * HZ / 1000)
static void pdc_console_poll(struct timer_list *unused);
static DEFINE_TIMER(pdc_console_timer, pdc_console_poll);
static struct tty_port tty_port;
static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp)
{
tty_port_tty_set(&tty_port, tty);
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
return 0;
return (c <= 0) ? NO_POLL_CHAR : c;
}
static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp)
static void kgdb_pdc_write_char(u8 chr)
{
if (tty->count == 1) {
del_timer_sync(&pdc_console_timer);
tty_port_tty_set(&tty_port, NULL);
}
if (PAGE0->mem_cons.cl_class != CL_DUPLEX)
pdc_console_write(NULL, &chr, 1);
}
static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
pdc_console_write(NULL, buf, count);
return count;
}
static unsigned int pdc_console_tty_write_room(struct tty_struct *tty)
{
return 32768; /* no limit, no buffer used */
}
static const struct tty_operations pdc_console_tty_ops = {
.open = pdc_console_tty_open,
.close = pdc_console_tty_close,
.write = pdc_console_tty_write,
.write_room = pdc_console_tty_write_room,
static struct kgdb_io kgdb_pdc_io_ops = {
.name = "kgdb_pdc",
.read_char = kgdb_pdc_read_char,
.write_char = kgdb_pdc_write_char,
};
static void pdc_console_poll(struct timer_list *unused)
{
int data, count = 0;
while (1) {
data = pdc_console_poll_key(NULL);
if (data == -1)
break;
tty_insert_flip_char(&tty_port, data & 0xFF, TTY_NORMAL);
count ++;
}
if (count)
tty_flip_buffer_push(&tty_port);
if (pdc_cons.flags & CON_ENABLED)
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
}
static struct tty_driver *pdc_console_tty_driver;
static int __init pdc_console_tty_driver_init(void)
{
struct tty_driver *driver;
int err;
/* Check if the console driver is still registered.
* It is unregistered if the pdc console was not selected as the
* primary console. */
struct console *tmp;
console_lock();
for_each_console(tmp)
if (tmp == &pdc_cons)
break;
console_unlock();
if (!tmp) {
printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name);
return -ENODEV;
}
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
pdc_cons.flags &= ~CON_BOOT;
driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS);
if (IS_ERR(driver))
return PTR_ERR(driver);
tty_port_init(&tty_port);
driver->driver_name = "pdc_cons";
driver->name = "ttyB";
driver->major = MUX_MAJOR;
driver->minor_start = 0;
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->init_termios = tty_std_termios;
tty_set_operations(driver, &pdc_console_tty_ops);
tty_port_link_device(&tty_port, driver, 0);
err = tty_register_driver(driver);
if (err) {
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
tty_port_destroy(&tty_port);
tty_driver_kref_put(driver);
return err;
}
pdc_console_tty_driver = driver;
return 0;
}
device_initcall(pdc_console_tty_driver_init);
static struct tty_driver * pdc_console_device (struct console *c, int *index)
{
*index = c->index;
return pdc_console_tty_driver;
}
#else
#define pdc_console_device NULL
#endif
static struct console pdc_cons = {
.name = "ttyB",
.write = pdc_console_write,
.device = pdc_console_device,
.setup = pdc_console_setup,
.flags = CON_BOOT | CON_PRINTBUFFER,
.index = -1,
};
static int pdc_console_initialized;
static void pdc_console_init_force(void)
static int __init pdc_earlycon_setup(struct earlycon_device *device,
const char *opt)
{
if (pdc_console_initialized)
return;
++pdc_console_initialized;
struct console *earlycon_console;
/* If the console is duplex then copy the COUT parameters to CIN. */
if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
/* register the pdc console */
register_console(&pdc_cons);
}
earlycon_console = device->con;
earlycon_console->write = pdc_console_write;
device->port.iotype = UPIO_MEM32BE;
void __init pdc_console_init(void)
{
#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
pdc_console_init_force();
#ifdef CONFIG_KGDB
kgdb_register_io_module(&kgdb_pdc_io_ops);
#endif
#ifdef EARLY_BOOTUP_DEBUG
printk(KERN_INFO "Initialized PDC Console for debugging.\n");
#endif
}
/*
* Used for emergencies. Currently only used if an HPMC occurs. If an
* HPMC occurs, it is possible that the current console may not be
* properly initialised after the PDC IO reset. This routine unregisters
* all of the current consoles, reinitializes the pdc console and
* registers it.
*/
void pdc_console_restart(void)
{
struct console *console;
if (pdc_console_initialized)
return;
/* If we've already seen the output, don't bother to print it again */
if (console_drivers != NULL)
pdc_cons.flags &= ~CON_PRINTBUFFER;
while ((console = console_drivers) != NULL)
unregister_console(console_drivers);
/* force registering the pdc console */
pdc_console_init_force();
return 0;
}
EARLYCON_DECLARE(pdc, pdc_earlycon_setup);
......@@ -70,6 +70,10 @@ void __init setup_cmdline(char **cmdline_p)
strlcat(p, "tty0", COMMAND_LINE_SIZE);
}
/* default to use early console */
if (!strstr(p, "earlycon"))
strlcat(p, " earlycon=pdc", COMMAND_LINE_SIZE);
#ifdef CONFIG_BLK_DEV_INITRD
if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
{
......@@ -139,8 +143,6 @@ void __init setup_arch(char **cmdline_p)
if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
panic("KERNEL_INITIAL_ORDER too small!");
pdc_console_init();
#ifdef CONFIG_64BIT
if(parisc_narrow_firmware) {
printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
......
......@@ -239,13 +239,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
/* unlock the pdc lock if necessary */
pdc_emergency_unlock();
/* maybe the kernel hasn't booted very far yet and hasn't been able
* to initialize the serial or STI console. In that case we should
* re-enable the pdc console, so that the user will be able to
* identify the problem. */
if (!console_drivers)
pdc_console_restart();
if (err)
printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
current->comm, task_pid_nr(current), str, err);
......@@ -429,10 +422,6 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
/* unlock the pdc lock if necessary */
pdc_emergency_unlock();
/* restart pdc console if necessary */
if (!console_drivers)
pdc_console_restart();
/* Not all paths will gutter the processor... */
switch(code){
......@@ -482,9 +471,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
unsigned long fault_space = 0;
int si_code;
if (code == 1)
pdc_console_restart(); /* switch back to pdc if HPMC */
else if (!irqs_disabled_flags(regs->gr[0]))
if (!irqs_disabled_flags(regs->gr[0]))
local_irq_enable();
/* Security check:
......
......@@ -393,7 +393,7 @@ static int parse_slot_config(int slot,
}
if (p0 + function_len < pos) {
printk(KERN_ERR "eisa_enumerator: function %d length mis-match "
printk(KERN_ERR "eisa_enumerator: function %d length mismatch "
"got %d, expected %d\n",
num_func, pos-p0, function_len);
res=-1;
......@@ -407,13 +407,13 @@ static int parse_slot_config(int slot,
}
if (pos != es->config_data_length) {
printk(KERN_ERR "eisa_enumerator: config data length mis-match got %d, expected %d\n",
printk(KERN_ERR "eisa_enumerator: config data length mismatch got %d, expected %d\n",
pos, es->config_data_length);
res=-1;
}
if (num_func != es->num_functions) {
printk(KERN_ERR "eisa_enumerator: number of functions mis-match got %d, expected %d\n",
printk(KERN_ERR "eisa_enumerator: number of functions mismatch got %d, expected %d\n",
num_func, es->num_functions);
res=-2;
}
......@@ -451,7 +451,7 @@ static int init_slot(int slot, struct eeprom_eisa_slot_info *es)
}
if (es->eisa_slot_id != id) {
print_eisa_id(id_string, id);
printk(KERN_ERR "EISA slot %d id mis-match: got %s",
printk(KERN_ERR "EISA slot %d id mismatch: got %s",
slot, id_string);
print_eisa_id(id_string, es->eisa_slot_id);
......
......@@ -603,21 +603,6 @@ config SERIAL_MUX_CONSOLE
select SERIAL_CORE_CONSOLE
default y
config PDC_CONSOLE
bool "PDC software console support"
depends on PARISC && !SERIAL_MUX && VT
help
Saying Y here will enable the software based PDC console to be
used as the system console. This is useful for machines in
which the hardware based console has not been written yet. The
following steps must be completed to use the PDC console:
1. create the device entry (mknod /dev/ttyB0 c 11 0)
2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
3. Add device ttyB0 to /etc/securetty (if you want to log on as
root on this console.)
4. Change the kernel command console parameter to: console=ttyB0
config SERIAL_SUNSAB
tristate "Sun Siemens SAB82532 serial support"
depends on SPARC && PCI
......
......@@ -1298,7 +1298,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
/* limit fbsize to max visible screen size */
if (fix->smem_len > yres*fix->line_length)
fix->smem_len = yres*fix->line_length;
fix->smem_len = ALIGN(yres*fix->line_length, 4*1024*1024);
fix->accel = FB_ACCEL_NONE;
......
......@@ -121,7 +121,7 @@ config KDB_DEFAULT_ENABLE
config KDB_KEYBOARD
bool "KGDB_KDB: keyboard as input device"
depends on VT && KGDB_KDB
depends on VT && KGDB_KDB && !PARISC
default n
help
KDB can use a PS/2 type keyboard for an input device
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment