diff options
Diffstat (limited to 'arch/microblaze/kernel')
-rw-r--r-- | arch/microblaze/kernel/cpu/cpuinfo.c | 1 | ||||
-rw-r--r-- | arch/microblaze/kernel/entry.S | 46 | ||||
-rw-r--r-- | arch/microblaze/kernel/exceptions.c | 3 | ||||
-rw-r--r-- | arch/microblaze/kernel/hw_exception_handler.S | 9 | ||||
-rw-r--r-- | arch/microblaze/kernel/prom.c | 8 | ||||
-rw-r--r-- | arch/microblaze/kernel/prom_parse.c | 115 | ||||
-rw-r--r-- | arch/microblaze/kernel/vmlinux.lds.S | 16 |
7 files changed, 58 insertions, 140 deletions
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 87c79fa..2c309fc 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -32,6 +32,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"7.30.a", 0x10}, {"7.30.b", 0x11}, {"8.00.a", 0x12}, + {"8.00.b", 0x13}, {NULL, 0}, }; diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 819238b..41c30cd 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -287,25 +287,44 @@ * are masked. This is nice, means we don't have to CLI before state save */ C_ENTRY(_user_exception): - addi r14, r14, 4 /* return address is 4 byte after call */ swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ + addi r14, r14, 4 /* return address is 4 byte after call */ + + mfs r1, rmsr + nop + andi r1, r1, MSR_UMS + bnei r1, 1f + +/* Kernel-mode state save - kernel execve */ + lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ + tophys(r1,r1); + + addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ + SAVE_REGS + swi r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */ + brid 2f; + nop; /* Fill delay slot */ + +/* User-mode state save. */ +1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ tophys(r1,r1); lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ - /* MS these three instructions can be added to one */ - /* addik r1, r1, THREAD_SIZE; */ - /* tophys(r1,r1); */ - /* addik r1, r1, -STATE_SAVE_SIZE; */ - addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; +/* calculate kernel stack pointer from task struct 8k */ + addik r1, r1, THREAD_SIZE; + tophys(r1,r1); + + addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ SAVE_REGS swi r0, r1, PTO + PT_R3 swi r0, r1, PTO + PT_R4 + swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); swi r11, r1, PTO+PT_R1; /* Store user SP. */ clear_ums; - lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); +2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* Save away the syscall number. */ swi r12, r1, PTO+PT_R0; tovirt(r1,r1) @@ -375,6 +394,9 @@ C_ENTRY(ret_from_trap): swi r3, r1, PTO + PT_R3 swi r4, r1, PTO + PT_R4 + lwi r11, r1, PTO + PT_MODE; +/* See if returning to kernel mode, if so, skip resched &c. */ + bnei r11, 2f; /* We're returning to user mode, so check for various conditions that * trigger rescheduling. */ /* FIXME: Restructure all these flag checks. */ @@ -417,6 +439,16 @@ C_ENTRY(ret_from_trap): RESTORE_REGS; addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ + bri 6f; + +/* Return to kernel state. */ +2: set_bip; /* Ints masked for state restore */ + VM_OFF; + tophys(r1,r1); + RESTORE_REGS; + addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ + tovirt(r1,r1); +6: TRAP_return: /* Make global symbol for debugging */ rtbd r14, 0; /* Instructions to return from an IRQ */ nop; diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c index 478f294..a7fa6ae 100644 --- a/arch/microblaze/kernel/exceptions.c +++ b/arch/microblaze/kernel/exceptions.c @@ -25,6 +25,7 @@ #include <linux/errno.h> #include <linux/ptrace.h> #include <asm/current.h> +#include <asm/cacheflush.h> #define MICROBLAZE_ILL_OPCODE_EXCEPTION 0x02 #define MICROBLAZE_IBUS_EXCEPTION 0x03 @@ -52,6 +53,8 @@ void die(const char *str, struct pt_regs *fp, long err) void sw_exception(struct pt_regs *regs) { _exception(SIGTRAP, regs, TRAP_BRKPT, regs->r16); + flush_dcache_range(regs->r16, regs->r16 + 0x4); + flush_icache_range(regs->r16, regs->r16 + 0x4); } void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index 7811954..25f6e07 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -945,11 +945,20 @@ store3: sbi r3, r4, 2; store4: sbi r3, r4, 3; /* Delay slot */ ex_shw_vm: /* Store the lower half-word, byte-by-byte into destination address */ +#ifdef __MICROBLAZEEL__ + lbui r3, r5, 0; +store5: sbi r3, r4, 0; + lbui r3, r5, 1; + brid ret_from_exc; +store6: sbi r3, r4, 1; /* Delay slot */ +#else lbui r3, r5, 2; store5: sbi r3, r4, 0; lbui r3, r5, 3; brid ret_from_exc; store6: sbi r3, r4, 1; /* Delay slot */ +#endif + ex_sw_end_vm: /* Exception handling of store word, ends. */ /* We have to prevent cases that get/put_user macros get unaligned pointer diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index a105301..bceaa55 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -47,9 +47,9 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) memblock_add(base, size); } -u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { - return memblock_alloc(size, align); + return __va(memblock_alloc(size, align)); } #ifdef CONFIG_EARLY_PRINTK @@ -61,14 +61,12 @@ static int __init early_init_dt_scan_serial(unsigned long node, char *p; int *addr; - pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname); /* find all serial nodes */ if (strncmp(uname, "serial", 6) != 0) return 0; - early_init_dt_check_for_initrd(node); - /* find compatible node with uartlite */ p = of_get_flat_dt_prop(node, "compatible", &l); if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) && diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c index 99d9b61..47187cc 100644 --- a/arch/microblaze/kernel/prom_parse.c +++ b/arch/microblaze/kernel/prom_parse.c @@ -2,88 +2,11 @@ #include <linux/kernel.h> #include <linux/string.h> -#include <linux/pci_regs.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/etherdevice.h> #include <linux/of_address.h> #include <asm/prom.h> -#include <asm/pci-bridge.h> - -#ifdef CONFIG_PCI -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) -{ - struct device_node *dn, *ppnode; - struct pci_dev *ppdev; - u32 lspec; - u32 laddr[3]; - u8 pin; - int rc; - - /* Check if we have a device node, if yes, fallback to standard OF - * parsing - */ - dn = pci_device_to_OF_node(pdev); - if (dn) - return of_irq_map_one(dn, 0, out_irq); - - /* Ok, we don't, time to have fun. Let's start by building up an - * interrupt spec. we assume #interrupt-cells is 1, which is standard - * for PCI. If you do different, then don't use that routine. - */ - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); - if (rc != 0) - return rc; - /* No pin, exit */ - if (pin == 0) - return -ENODEV; - - /* Now we walk up the PCI tree */ - lspec = pin; - for (;;) { - /* Get the pci_dev of our parent */ - ppdev = pdev->bus->self; - - /* Ouch, it's a host bridge... */ - if (ppdev == NULL) { - struct pci_controller *host; - host = pci_bus_to_host(pdev->bus); - ppnode = host ? host->dn : NULL; - /* No node for host bridge ? give up */ - if (ppnode == NULL) - return -EINVAL; - } else - /* We found a P2P bridge, check if it has a node */ - ppnode = pci_device_to_OF_node(ppdev); - - /* Ok, we have found a parent with a device-node, hand over to - * the OF parsing code. - * We build a unit address from the linux device to be used for - * resolution. Note that we use the linux bus number which may - * not match your firmware bus numbering. - * Fortunately, in most cases, interrupt-map-mask doesn't - * include the bus number as part of the matching. - * You should still be careful about that though if you intend - * to rely on this function (you ship a firmware that doesn't - * create device nodes for all PCI devices). - */ - if (ppnode) - break; - - /* We can only get here if we hit a P2P bridge with no node, - * let's do standard swizzling and try again - */ - lspec = pci_swizzle_interrupt_pin(pdev, lspec); - pdev = ppdev; - } - - laddr[0] = (pdev->bus->number << 16) - | (pdev->devfn << 8); - laddr[1] = laddr[2] = 0; - return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); -} -EXPORT_SYMBOL_GPL(of_irq_map_pci); -#endif /* CONFIG_PCI */ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, unsigned long *busno, unsigned long *phys, unsigned long *size) @@ -110,41 +33,3 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, cells = prop ? *(u32 *)prop : of_n_size_cells(dn); *size = of_read_number(dma_window, cells); } - -/** - * Search the device tree for the best MAC address to use. 'mac-address' is - * checked first, because that is supposed to contain to "most recent" MAC - * address. If that isn't set, then 'local-mac-address' is checked next, - * because that is the default address. If that isn't set, then the obsolete - * 'address' is checked, just in case we're using an old device tree. - * - * Note that the 'address' property is supposed to contain a virtual address of - * the register set, but some DTS files have redefined that property to be the - * MAC address. - * - * All-zero MAC addresses are rejected, because those could be properties that - * exist in the device tree, but were not set by U-Boot. For example, the - * DTS could define 'mac-address' and 'local-mac-address', with zero MAC - * addresses. Some older U-Boots only initialized 'local-mac-address'. In - * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists - * but is all zeros. -*/ -const void *of_get_mac_address(struct device_node *np) -{ - struct property *pp; - - pp = of_find_property(np, "mac-address", NULL); - if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) - return pp->value; - - pp = of_find_property(np, "local-mac-address", NULL); - if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) - return pp->value; - - pp = of_find_property(np, "address", NULL); - if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) - return pp->value; - - return NULL; -} -EXPORT_SYMBOL(of_get_mac_address); diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index 96a88c3..3451bde 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -123,20 +123,10 @@ SECTIONS { __init_end_before_initramfs = .; - .init.ramfs ALIGN(PAGE_SIZE) : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - . = ALIGN(4); - LONG(0); -/* - * FIXME this can break initramfs for MMU. - * Pad init.ramfs up to page boundary, - * so that __init_end == __bss_start. This will make image.elf - * consistent with the image.bin - */ - /* . = ALIGN(PAGE_SIZE); */ + .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { + INIT_RAM_FS } + __init_end = .; .bss ALIGN (PAGE_SIZE) : AT(ADDR(.bss) - LOAD_OFFSET) { |