Changeset 965dc18 in mainline for kernel/arch/sparc64/src


Ignore:
Timestamp:
2008-12-05T19:59:03Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
49093a4
Parents:
0258e67
Message:

Merge sparc branch to trunk.

Location:
kernel/arch/sparc64/src
Files:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/src/console.c

    r0258e67 r965dc18  
    3939#include <arch/drivers/kbd.h>
    4040
     41#include <arch/drivers/sgcn.h>
     42
    4143#ifdef CONFIG_Z8530
    4244#include <genarch/kbd/z8530.h>
     
    5557#include <arch.h>
    5658#include <panic.h>
     59#include <func.h>
    5760#include <print.h>
    5861
    5962#define KEYBOARD_POLL_PAUSE     50000   /* 50ms */
    6063
    61 /** Initialize kernel console to use framebuffer and keyboard directly. */
    62 void standalone_sparc64_console_init(void)
     64/**
     65 * Initialize kernel console to use framebuffer and keyboard directly.
     66 * Called on UltraSPARC machines with standard keyboard and framebuffer.
     67 *
     68 * @param aliases       the "/aliases" OBP node
     69 */
     70static void standard_console_init(ofw_tree_node_t *aliases)
    6371{
    6472        stdin = NULL;
    6573
    66         ofw_tree_node_t *aliases;
    6774        ofw_tree_property_t *prop;
    6875        ofw_tree_node_t *screen;
    6976        ofw_tree_node_t *keyboard;
    70        
    71         aliases = ofw_tree_lookup("/aliases");
    72         if (!aliases)
    73                 panic("Can't find /aliases.\n");
    7477       
    7578        prop = ofw_tree_getprop(aliases, "screen");
     
    9699}
    97100
     101/** Initilize I/O on the Serengeti machine. */
     102static void serengeti_init(void)
     103{
     104        sgcn_init();
     105}
     106
     107/**
     108 * Initialize input/output. Auto-detects the type of machine
     109 * and calls the appropriate I/O init routine.
     110 */
     111void standalone_sparc64_console_init(void)
     112{
     113        ofw_tree_node_t *aliases;
     114        ofw_tree_property_t *prop;
     115       
     116        aliases = ofw_tree_lookup("/aliases");
     117        if (!aliases)
     118                panic("Can't find /aliases.\n");
     119       
     120        /* "def-cn" = "default console" */
     121        prop = ofw_tree_getprop(aliases, "def-cn");
     122       
     123        if ((!prop) || (!prop->value) || (strcmp(prop->value, "/sgcn") != 0)) {
     124                standard_console_init(aliases);
     125        } else {
     126                serengeti_init();
     127        }
     128}
     129
     130
    98131/** Kernel thread for polling keyboard.
    99132 *
     
    130163#endif
    131164#endif
     165#ifdef CONFIG_SGCN
     166                if (kbd_type == KBD_SGCN)
     167                        sgcn_poll();
     168#endif
    132169                thread_usleep(KEYBOARD_POLL_PAUSE);
    133170        }
     
    150187                break;
    151188#endif
     189#ifdef CONFIG_SGCN
     190        case KBD_SGCN:
     191                sgcn_grab();
     192                break;
     193#endif
    152194        default:
    153195                break;
     
    171213                break;
    172214#endif
     215#ifdef CONFIG_SGCN
     216        case KBD_SGCN:
     217                sgcn_release();
     218                break;
     219#endif
    173220        default:
    174221                break;
  • kernel/arch/sparc64/src/cpu/cpu.c

    r0258e67 r965dc18  
    3333 */
    3434
     35#include <arch/cpu_family.h>
    3536#include <cpu.h>
    3637#include <arch.h>
     
    3839#include <arch/drivers/tick.h>
    3940#include <print.h>
     41#include <arch/cpu_node.h>
     42
     43/**
     44 * Finds out the clock frequency of the current CPU.
     45 *
     46 * @param node  node representing the current CPU in the OFW tree
     47 * @return      clock frequency if "node" is the current CPU and no error
     48 *              occurs, -1 if "node" is not the current CPU or on error
     49 */
     50static int find_cpu_frequency(ofw_tree_node_t *node)
     51{
     52        ofw_tree_property_t *prop;
     53        uint32_t mid;
     54
     55        /* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
     56        prop = ofw_tree_getprop(node, "upa-portid");
     57        if ((!prop) || (!prop->value))
     58                prop = ofw_tree_getprop(node, "portid");
     59        if ((!prop) || (!prop->value))
     60                prop = ofw_tree_getprop(node, "cpuid");
     61       
     62        if (prop && prop->value) {
     63                mid = *((uint32_t *) prop->value);
     64                if (mid == CPU->arch.mid) {
     65                        prop = ofw_tree_getprop(node, "clock-frequency");
     66                        if (prop && prop->value) {
     67                                return *((uint32_t *) prop->value);
     68                        }
     69                }
     70        }
     71       
     72        return -1;
     73}
    4074
    4175/** Perform sparc64 specific initialization of the processor structure for the
     
    4579{
    4680        ofw_tree_node_t *node;
    47         uint32_t mid;
    4881        uint32_t clock_frequency = 0;
    49         upa_config_t upa_config;
    5082       
    51         upa_config.value = upa_config_read();
    52         CPU->arch.mid = upa_config.mid;
     83        CPU->arch.mid = read_mid();
    5384       
    5485        /*
    5586         * Detect processor frequency.
    5687         */
    57         node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
    58         while (node) {
    59                 ofw_tree_property_t *prop;
     88        if (is_us() || is_us_iii()) {
     89                node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
     90                while (node) {
     91                        int f = find_cpu_frequency(node);
     92                        if (f != -1)
     93                                clock_frequency = (uint32_t) f;
     94                        node = ofw_tree_find_peer_by_device_type(node, "cpu");
     95                }
     96        } else if (is_us_iv()) {
     97                node = ofw_tree_find_child(cpus_parent(), "cmp");
     98                while (node) {
     99                        int f;
     100                        f = find_cpu_frequency(
     101                                ofw_tree_find_child(node, "cpu@0"));
     102                        if (f != -1)
     103                                clock_frequency = (uint32_t) f;
     104                        f = find_cpu_frequency(
     105                                ofw_tree_find_child(node, "cpu@1"));
     106                        if (f != -1)
     107                                clock_frequency = (uint32_t) f;
     108                        node = ofw_tree_find_peer_by_name(node, "cmp");
     109                }
     110        }
    60111               
    61                 prop = ofw_tree_getprop(node, "upa-portid");
    62                 if (prop && prop->value) {
    63                         mid = *((uint32_t *) prop->value);
    64                         if (mid == CPU->arch.mid) {
    65                                 prop = ofw_tree_getprop(node,
    66                                     "clock-frequency");
    67                                 if (prop && prop->value)
    68                                         clock_frequency = *((uint32_t *)
    69                                             prop->value);
    70                         }
    71                 }
    72                 node = ofw_tree_find_peer_by_device_type(node, "cpu");
    73         }
    74 
    75112        CPU->arch.clock_frequency = clock_frequency;
    76113        tick_init();
     
    125162                impl = "UltraSPARC III";
    126163                break;
     164        case IMPL_ULTRASPARCIII_PLUS:
     165                impl = "UltraSPARC III+";
     166                break;
     167        case IMPL_ULTRASPARCIII_I:
     168                impl = "UltraSPARC IIIi";
     169                break;
     170        case IMPL_ULTRASPARCIV:
     171                impl = "UltraSPARC IV";
     172                break;
    127173        case IMPL_ULTRASPARCIV_PLUS:
    128174                impl = "UltraSPARC IV+";
  • kernel/arch/sparc64/src/ddi/ddi.c

    r0258e67 r965dc18  
    4242 *
    4343 * @param task Task.
    44  * @param ioaddr Startign I/O space address.
     44 * @param ioaddr Starting I/O space address.
    4545 * @param size Size of the enabled I/O range.
    4646 *
  • kernel/arch/sparc64/src/drivers/scr.c

    r0258e67 r965dc18  
    5656{
    5757        ofw_tree_property_t *prop;
     58        ofw_pci_reg_t *pci_reg;
     59        ofw_pci_reg_t pci_abs_reg;
     60        ofw_upa_reg_t *upa_reg;
     61        ofw_sbus_reg_t *sbus_reg;
    5862        const char *name;
    5963       
     
    6266        if (strcmp(name, "SUNW,m64B") == 0)
    6367                scr_type = SCR_ATYFB;
     68        else if (strcmp(name, "SUNW,XVR-100") == 0)
     69                scr_type = SCR_XVR;
    6470        else if (strcmp(name, "SUNW,ffb") == 0)
    6571                scr_type = SCR_FFB;
     
    6874       
    6975        if (scr_type == SCR_UNKNOWN) {
    70                 printf("Unknown keyboard device.\n");
     76                printf("Unknown screen device.\n");
    7177                return;
    7278        }
     
    107113                }
    108114       
    109                 ofw_pci_reg_t *fb_reg = &((ofw_pci_reg_t *) prop->value)[1];
    110                 ofw_pci_reg_t abs_reg;
    111                
    112                 if (!ofw_pci_reg_absolutize(node, fb_reg, &abs_reg)) {
     115                pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
     116               
     117                if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
    113118                        printf("Failed to absolutize fb register.\n");
    114119                        return;
    115120                }
    116121       
    117                 if (!ofw_pci_apply_ranges(node->parent, &abs_reg , &fb_addr)) {
     122                if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
     123                    &fb_addr)) {
    118124                        printf("Failed to determine screen address.\n");
    119125                        return;
     
    143149               
    144150                break;
     151        case SCR_XVR:
     152                if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
     153                        printf("Too few screen registers.\n");
     154                        return;
     155                }
     156       
     157                pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
     158               
     159                if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
     160                        printf("Failed to absolutize fb register.\n");
     161                        return;
     162                }
     163       
     164                if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
     165                    &fb_addr)) {
     166                        printf("Failed to determine screen address.\n");
     167                        return;
     168                }
     169
     170                switch (fb_depth) {
     171                case 8:
     172                        fb_scanline = fb_linebytes * (fb_depth >> 3);
     173                        visual = VISUAL_SB1500_PALETTE;
     174                        break;
     175                case 16:
     176                        fb_scanline = fb_linebytes * (fb_depth >> 3);
     177                        visual = VISUAL_RGB_5_6_5;
     178                        break;
     179                case 24:
     180                        fb_scanline = fb_linebytes * 4;
     181                        visual = VISUAL_RGB_8_8_8_0;
     182                        break;
     183                case 32:
     184                        fb_scanline = fb_linebytes * (fb_depth >> 3);
     185                        visual = VISUAL_RGB_0_8_8_8;
     186                        break;
     187                default:
     188                        printf("Unsupported bits per pixel.\n");
     189                        return;
     190                }
     191               
     192                break;
    145193        case SCR_FFB:   
    146194                fb_scanline = 8192;
    147195                visual = VISUAL_BGR_0_8_8_8;
    148196
    149                 ofw_upa_reg_t *reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
    150                 if (!ofw_upa_apply_ranges(node->parent, reg, &fb_addr)) {
     197                upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
     198                if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) {
    151199                        printf("Failed to determine screen address.\n");
    152200                        return;
     
    165213                }
    166214               
    167                 ofw_sbus_reg_t *cg6_reg = &((ofw_sbus_reg_t *) prop->value)[0];
    168                 if (!ofw_sbus_apply_ranges(node->parent, cg6_reg, &fb_addr)) {
     215                sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0];
     216                if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) {
    169217                        printf("Failed to determine screen address.\n");
    170218                        return;
     
    176224        }
    177225
    178         fb_init(fb_addr, fb_width, fb_height, fb_scanline, visual);
     226        fb_properties_t props = {
     227                .addr = fb_addr,
     228                .offset = 0,
     229                .x = fb_width,
     230                .y = fb_height,
     231                .scan = fb_scanline,
     232                .visual = visual,
     233        };
     234        fb_init(&props);
    179235}
    180236
  • kernel/arch/sparc64/src/drivers/tick.c

    r0258e67 r965dc18  
    4646#define TICK_RESTART_TIME       50      /* Worst case estimate. */
    4747
    48 /** Initialize tick interrupt. */
     48/** Initialize tick and stick interrupt. */
    4949void tick_init(void)
    5050{
     51        /* initialize TICK interrupt */
    5152        tick_compare_reg_t compare;
    52        
     53
    5354        interrupt_register(14, "tick_int", tick_interrupt);
    5455        compare.int_dis = false;
     
    5758        tick_compare_write(compare.value);
    5859        tick_write(0);
     60
     61#if defined (US3)
     62        /* disable STICK interrupts and clear any pending ones */
     63        tick_compare_reg_t stick_compare;
     64        softint_reg_t clear;
     65
     66        stick_compare.value = stick_compare_read();
     67        stick_compare.int_dis = true;
     68        stick_compare.tick_cmpr = 0;
     69        stick_compare_write(stick_compare.value);
     70
     71        clear.value = 0;
     72        clear.stick_int = 1;
     73        clear_softint_write(clear.value);
     74#endif
    5975}
    6076
     
    6884        softint_reg_t softint, clear;
    6985        uint64_t drift;
    70        
     86
    7187        softint.value = softint_read();
    7288       
  • kernel/arch/sparc64/src/mm/as.c

    r0258e67 r965dc18  
    165165        tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
    166166        dtsb_base_write(tsb_base.value);
     167       
     168#if defined (US3)
     169        /*
     170         * Clear the extension registers.
     171         * In HelenOS, primary and secondary context registers contain
     172         * equal values and kernel misses (context 0, ie. the nucleus context)
     173         * are excluded from the TSB miss handler, so it makes no sense
     174         * to have separate TSBs for primary, secondary and nucleus contexts.
     175         * Clearing the extension registers will ensure that the value of the
     176         * TSB Base register will be used as an address of TSB, making the code
     177         * compatible with the US port.
     178         */
     179        itsb_primary_extension_write(0);
     180        itsb_nucleus_extension_write(0);
     181        dtsb_primary_extension_write(0);
     182        dtsb_secondary_extension_write(0);
     183        dtsb_nucleus_extension_write(0);
     184#endif
    167185#endif
    168186}
  • kernel/arch/sparc64/src/mm/cache.S

    r0258e67 r965dc18  
    4848        ! beware SF Erratum #51, do not put the MEMBAR here
    4949        nop                             
    50 
    51 /** Flush only D-cache lines of one virtual color.
    52  *
    53  * @param o0    Virtual color to be flushed.
    54  */
    55 .global dcache_flush_color
    56 dcache_flush_color:
    57         mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
    58         set DCACHE_SIZE / 2, %g2
    59         sllx %g2, %o0, %g2
    60         sub %g2, DCACHE_LINE_SIZE, %g2
    61 0:      stxa %g0, [%g2] ASI_DCACHE_TAG
    62         membar #Sync
    63         subcc %g1, 1, %g1
    64         bnz,pt %xcc, 0b
    65         sub %g2, DCACHE_LINE_SIZE, %g2
    66         retl
    67         nop
    68 
    69 /** Flush only D-cache lines of one virtual color and one tag.
    70  *
    71  * @param o0    Virtual color to lookup the tag.
    72  * @param o1    Tag of the cachelines to be flushed.
    73  */
    74 .global dcache_flush_tag
    75 dcache_flush_tag:
    76         mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
    77         set DCACHE_SIZE / 2, %g2
    78         sllx %g2, %o0, %g2
    79         sub %g2, DCACHE_LINE_SIZE, %g2
    80 0:      ldxa [%g2] ASI_DCACHE_TAG, %g3
    81         srlx %g3, DCACHE_TAG_SHIFT, %g3
    82         cmp %g3, %o1
    83         bnz 1f
    84         nop
    85         stxa %g0, [%g2] ASI_DCACHE_TAG
    86         membar #Sync
    87 1:      subcc %g1, 1, %g1
    88         bnz,pt %xcc, 0b
    89         sub %g2, DCACHE_LINE_SIZE, %g2
    90         retl
    91         nop
  • kernel/arch/sparc64/src/mm/page.c

    r0258e67 r965dc18  
    5353        uintptr_t phys_page;
    5454        int pagesize_code;
    55 } bsp_locked_dtlb_entry[DTLB_ENTRY_COUNT];
     55} bsp_locked_dtlb_entry[DTLB_MAX_LOCKED_ENTRIES];
    5656
    5757/** Number of entries in bsp_locked_dtlb_entry array. */
     
    167167/** @}
    168168 */
     169
  • kernel/arch/sparc64/src/mm/tlb.c

    r0258e67 r965dc18  
    5555#endif
    5656
    57 static void dtlb_pte_copy(pte_t *t, index_t index, bool ro);
    58 static void itlb_pte_copy(pte_t *t, index_t index);
    59 static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
    60     const char *str);
    61 static void do_fast_data_access_mmu_miss_fault(istate_t *istate,
    62     tlb_tag_access_reg_t tag, const char *str);
    63 static void do_fast_data_access_protection_fault(istate_t *istate,
    64     tlb_tag_access_reg_t tag, const char *str);
     57static void dtlb_pte_copy(pte_t *, index_t, bool);
     58static void itlb_pte_copy(pte_t *, index_t);
     59static void do_fast_instruction_access_mmu_miss_fault(istate_t *, const char *);
     60static void do_fast_data_access_mmu_miss_fault(istate_t *, tlb_tag_access_reg_t,
     61    const char *);
     62static void do_fast_data_access_protection_fault(istate_t *,
     63    tlb_tag_access_reg_t, const char *);
    6564
    6665char *context_encoding[] = {
     
    8786/** Insert privileged mapping into DMMU TLB.
    8887 *
    89  * @param page Virtual page address.
    90  * @param frame Physical frame address.
    91  * @param pagesize Page size.
    92  * @param locked True for permanent mappings, false otherwise.
    93  * @param cacheable True if the mapping is cacheable, false otherwise.
     88 * @param page          Virtual page address.
     89 * @param frame         Physical frame address.
     90 * @param pagesize      Page size.
     91 * @param locked        True for permanent mappings, false otherwise.
     92 * @param cacheable     True if the mapping is cacheable, false otherwise.
    9493 */
    9594void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize,
     
    104103        fr.address = frame;
    105104
    106         tag.value = ASID_KERNEL;
     105        tag.context = ASID_KERNEL;
    107106        tag.vpn = pg.vpn;
    108107
     
    127126/** Copy PTE to TLB.
    128127 *
    129  * @param t     Page Table Entry to be copied.
    130  * @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
    131  * @param ro    If true, the entry will be created read-only, regardless of its
    132  *              w field.
     128 * @param t             Page Table Entry to be copied.
     129 * @param index         Zero if lower 8K-subpage, one if higher 8K-subpage.
     130 * @param ro            If true, the entry will be created read-only, regardless
     131 *                      of its w field.
    133132 */
    134133void dtlb_pte_copy(pte_t *t, index_t index, bool ro)
     
    166165/** Copy PTE to ITLB.
    167166 *
    168  * @param t     Page Table Entry to be copied.
    169  * @param index Zero if lower 8K-subpage, one if higher 8K-subpage.
     167 * @param t             Page Table Entry to be copied.
     168 * @param index         Zero if lower 8K-subpage, one if higher 8K-subpage.
    170169 */
    171170void itlb_pte_copy(pte_t *t, index_t index)
     
    236235 * low-level, assembly language part of the fast_data_access_mmu_miss handler.
    237236 *
    238  * @param tag Content of the TLB Tag Access register as it existed when the
    239  *    trap happened. This is to prevent confusion created by clobbered
    240  *    Tag Access register during a nested DTLB miss.
    241  * @param istate Interrupted state saved on the stack.
     237 * @param tag           Content of the TLB Tag Access register as it existed
     238 *                      when the trap happened. This is to prevent confusion
     239 *                      created by clobbered Tag Access register during a nested
     240 *                      DTLB miss.
     241 * @param istate        Interrupted state saved on the stack.
    242242 */
    243243void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate)
     
    288288/** DTLB protection fault handler.
    289289 *
    290  * @param tag Content of the TLB Tag Access register as it existed when the
    291  *    trap happened. This is to prevent confusion created by clobbered
    292  *    Tag Access register during a nested DTLB miss.
    293  * @param istate Interrupted state saved on the stack.
     290 * @param tag           Content of the TLB Tag Access register as it existed
     291 *                      when the trap happened. This is to prevent confusion
     292 *                      created by clobbered Tag Access register during a nested
     293 *                      DTLB miss.
     294 * @param istate        Interrupted state saved on the stack.
    294295 */
    295296void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
     
    332333}
    333334
     335/** Print TLB entry (for debugging purposes).
     336 *
     337 * The diag field has been left out in order to make this function more generic
     338 * (there is no diag field in US3 architeture).
     339 *
     340 * @param i             TLB entry number
     341 * @param t             TLB entry tag
     342 * @param d             TLB entry data
     343 */
     344static void print_tlb_entry(int i, tlb_tag_read_reg_t t, tlb_data_t d)
     345{
     346        printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
     347            "ie=%d, soft2=%#x, pfn=%#x, soft=%#x, l=%d, "
     348            "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
     349            t.context, d.v, d.size, d.nfo, d.ie, d.soft2,
     350            d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
     351}
     352
     353#if defined (US)
     354
    334355/** Print contents of both TLBs. */
    335356void tlb_print(void)
     
    343364                d.value = itlb_data_access_read(i);
    344365                t.value = itlb_tag_read_read(i);
    345 
    346                 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
    347                     "ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
    348                     "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
    349                     t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
    350                     d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
     366                print_tlb_entry(i, t, d);
    351367        }
    352368
     
    355371                d.value = dtlb_data_access_read(i);
    356372                t.value = dtlb_tag_read_read(i);
    357                
    358                 printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
    359                     "ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
    360                     "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
    361                     t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
    362                     d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
    363         }
    364 
    365 }
     373                print_tlb_entry(i, t, d);
     374        }
     375}
     376
     377#elif defined (US3)
     378
     379/** Print contents of all TLBs. */
     380void tlb_print(void)
     381{
     382        int i;
     383        tlb_data_t d;
     384        tlb_tag_read_reg_t t;
     385       
     386        printf("TLB_ISMALL contents:\n");
     387        for (i = 0; i < tlb_ismall_size(); i++) {
     388                d.value = dtlb_data_access_read(TLB_ISMALL, i);
     389                t.value = dtlb_tag_read_read(TLB_ISMALL, i);
     390                print_tlb_entry(i, t, d);
     391        }
     392       
     393        printf("TLB_IBIG contents:\n");
     394        for (i = 0; i < tlb_ibig_size(); i++) {
     395                d.value = dtlb_data_access_read(TLB_IBIG, i);
     396                t.value = dtlb_tag_read_read(TLB_IBIG, i);
     397                print_tlb_entry(i, t, d);
     398        }
     399       
     400        printf("TLB_DSMALL contents:\n");
     401        for (i = 0; i < tlb_dsmall_size(); i++) {
     402                d.value = dtlb_data_access_read(TLB_DSMALL, i);
     403                t.value = dtlb_tag_read_read(TLB_DSMALL, i);
     404                print_tlb_entry(i, t, d);
     405        }
     406       
     407        printf("TLB_DBIG_1 contents:\n");
     408        for (i = 0; i < tlb_dbig_size(); i++) {
     409                d.value = dtlb_data_access_read(TLB_DBIG_0, i);
     410                t.value = dtlb_tag_read_read(TLB_DBIG_0, i);
     411                print_tlb_entry(i, t, d);
     412        }
     413       
     414        printf("TLB_DBIG_2 contents:\n");
     415        for (i = 0; i < tlb_dbig_size(); i++) {
     416                d.value = dtlb_data_access_read(TLB_DBIG_1, i);
     417                t.value = dtlb_tag_read_read(TLB_DBIG_1, i);
     418                print_tlb_entry(i, t, d);
     419        }
     420}
     421
     422#endif
    366423
    367424void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
     
    412469        sfar = dtlb_sfar_read();
    413470       
     471#if defined (US)
    414472        printf("DTLB SFSR: asi=%#x, ft=%#x, e=%d, ct=%d, pr=%d, w=%d, ow=%d, "
    415473            "fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w,
    416474            sfsr.ow, sfsr.fv);
     475#elif defined (US3)
     476        printf("DTLB SFSR: nf=%d, asi=%#x, tm=%d, ft=%#x, e=%d, ct=%d, pr=%d, "
     477            "w=%d, ow=%d, fv=%d\n", sfsr.nf, sfsr.asi, sfsr.tm, sfsr.ft,
     478            sfsr.e, sfsr.ct, sfsr.pr, sfsr.w, sfsr.ow, sfsr.fv);
     479#endif
     480           
    417481        printf("DTLB SFAR: address=%p\n", sfar);
    418482       
    419483        dtlb_sfsr_write(0);
    420484}
     485
     486#if defined (US3)
     487/** Invalidates given TLB entry if and only if it is non-locked or global.
     488 *
     489 * @param tlb           TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1,
     490 *                      TLB_ISMALL, TLB_IBIG).
     491 * @param entry         Entry index within the given TLB.
     492 */
     493static void tlb_invalidate_entry(int tlb, index_t entry)
     494{
     495        tlb_data_t d;
     496        tlb_tag_read_reg_t t;
     497       
     498        if (tlb == TLB_DSMALL || tlb == TLB_DBIG_0 || tlb == TLB_DBIG_1) {
     499                d.value = dtlb_data_access_read(tlb, entry);
     500                if (!d.l || d.g) {
     501                        t.value = dtlb_tag_read_read(tlb, entry);
     502                        d.v = false;
     503                        dtlb_tag_access_write(t.value);
     504                        dtlb_data_access_write(tlb, entry, d.value);
     505                }
     506        } else if (tlb == TLB_ISMALL || tlb == TLB_IBIG) {
     507                d.value = itlb_data_access_read(tlb, entry);
     508                if (!d.l || d.g) {
     509                        t.value = itlb_tag_read_read(tlb, entry);
     510                        d.v = false;
     511                        itlb_tag_access_write(t.value);
     512                        itlb_data_access_write(tlb, entry, d.value);
     513                }
     514        }
     515}
     516#endif
    421517
    422518/** Invalidate all unlocked ITLB and DTLB entries. */
     
    424520{
    425521        int i;
    426         tlb_data_t d;
    427         tlb_tag_read_reg_t t;
    428 
     522       
    429523        /*
    430524         * Walk all ITLB and DTLB entries and remove all unlocked mappings.
    431525         *
    432526         * The kernel doesn't use global mappings so any locked global mappings
    433          * found  must have been created by someone else. Their only purpose now
     527         * found must have been created by someone else. Their only purpose now
    434528         * is to collide with proper mappings. Invalidate immediately. It should
    435529         * be safe to invalidate them as late as now.
    436530         */
     531
     532#if defined (US)
     533        tlb_data_t d;
     534        tlb_tag_read_reg_t t;
    437535
    438536        for (i = 0; i < ITLB_ENTRY_COUNT; i++) {
     
    445543                }
    446544        }
    447        
     545
    448546        for (i = 0; i < DTLB_ENTRY_COUNT; i++) {
    449547                d.value = dtlb_data_access_read(i);
     
    455553                }
    456554        }
    457        
     555
     556#elif defined (US3)
     557
     558        for (i = 0; i < tlb_ismall_size(); i++)
     559                tlb_invalidate_entry(TLB_ISMALL, i);
     560        for (i = 0; i < tlb_ibig_size(); i++)
     561                tlb_invalidate_entry(TLB_IBIG, i);
     562        for (i = 0; i < tlb_dsmall_size(); i++)
     563                tlb_invalidate_entry(TLB_DSMALL, i);
     564        for (i = 0; i < tlb_dbig_size(); i++)
     565                tlb_invalidate_entry(TLB_DBIG_0, i);
     566        for (i = 0; i < tlb_dbig_size(); i++)
     567                tlb_invalidate_entry(TLB_DBIG_1, i);
     568#endif
     569
    458570}
    459571
     
    485597 * address space.
    486598 *
    487  * @param asid Address Space ID.
    488  * @param page First page which to sweep out from ITLB and DTLB.
    489  * @param cnt Number of ITLB and DTLB entries to invalidate.
     599 * @param asid          Address Space ID.
     600 * @param page          First page which to sweep out from ITLB and DTLB.
     601 * @param cnt           Number of ITLB and DTLB entries to invalidate.
    490602 */
    491603void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
  • kernel/arch/sparc64/src/mm/tsb.c

    r0258e67 r965dc18  
    113113        tsb->data.size = PAGESIZE_8K;
    114114        tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
    115         tsb->data.cp = t->c;
    116         tsb->data.p = t->k;             /* p as privileged */
    117         tsb->data.v = t->p;
     115        tsb->data.cp = t->c;    /* cp as cache in phys.-idxed, c as cacheable */
     116        tsb->data.p = t->k;     /* p as privileged, k as kernel */
     117        tsb->data.v = t->p;     /* v as valid, p as present */
    118118       
    119119        write_barrier();
     
    174174/** @}
    175175 */
     176
  • kernel/arch/sparc64/src/smp/ipi.c

    r0258e67 r965dc18  
    4747#include <panic.h>
    4848
     49/** Set the contents of the outgoing interrupt vector data.
     50 *
     51 * The first data item (data 0) will be set to the value of func, the
     52 * rest of the vector will contain zeros.
     53 *
     54 * This is a helper function used from within the cross_call function.
     55 *
     56 * @param func value the first data item of the vector will be set to
     57 */
     58static inline void set_intr_w_data(void (* func)(void))
     59{
     60#if defined (US)
     61        asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
     62        asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
     63        asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
     64#elif defined (US3)
     65        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t) func);
     66        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
     67        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
     68        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
     69        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
     70        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
     71        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
     72        asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
     73#endif
     74}
     75
    4976/** Invoke function on another processor.
    5077 *
     
    74101                panic("Interrupt Dispatch Status busy bit set\n");
    75102       
     103        ASSERT(!(pstate_read() & PSTATE_IE_BIT));
     104       
    76105        do {
    77                 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_0,
    78                     (uintptr_t) func);
    79                 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
    80                 asi_u64_write(ASI_UDB_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
    81                 asi_u64_write(ASI_UDB_INTR_W,
     106                set_intr_w_data(func);
     107                asi_u64_write(ASI_INTR_W,
    82108                    (mid << INTR_VEC_DISPATCH_MID_SHIFT) |
    83                     ASI_UDB_INTR_W_DISPATCH, 0);
     109                    VA_INTR_W_DISPATCH, 0);
    84110       
    85111                membar();
  • kernel/arch/sparc64/src/smp/smp.c

    r0258e67 r965dc18  
    3636#include <genarch/ofw/ofw_tree.h>
    3737#include <cpu.h>
     38#include <arch/cpu_family.h>
    3839#include <arch/cpu.h>
    3940#include <arch.h>
     
    4445#include <synch/waitq.h>
    4546#include <print.h>
     47#include <arch/cpu_node.h>
    4648
    4749/**
     
    6264        count_t cnt = 0;
    6365       
    64         node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
    65         while (node) {
    66                 cnt++;
    67                 node = ofw_tree_find_peer_by_device_type(node, "cpu");
     66        if (is_us() || is_us_iii()) {
     67                node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
     68                while (node) {
     69                        cnt++;
     70                        node = ofw_tree_find_peer_by_device_type(node, "cpu");
     71                }
     72        } else if (is_us_iv()) {
     73                node = ofw_tree_find_child(cpus_parent(), "cmp");
     74                while (node) {
     75                        cnt += 2;
     76                        node = ofw_tree_find_peer_by_name(node, "cmp");
     77                }
    6878        }
    6979       
    7080        config.cpu_count = max(1, cnt);
     81}
     82
     83/**
     84 * Wakes up the CPU which is represented by the "node" OFW tree node.
     85 * If "node" represents the current CPU, calling the function has
     86 * no effect.
     87 */
     88static void wakeup_cpu(ofw_tree_node_t *node)
     89{
     90        uint32_t mid;
     91        ofw_tree_property_t *prop;
     92               
     93        /* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
     94        prop = ofw_tree_getprop(node, "upa-portid");
     95        if ((!prop) || (!prop->value))
     96                prop = ofw_tree_getprop(node, "portid");
     97        if ((!prop) || (!prop->value))
     98                prop = ofw_tree_getprop(node, "cpuid");
     99               
     100        if (!prop || prop->value == NULL)
     101                return;
     102               
     103        mid = *((uint32_t *) prop->value);
     104        if (CPU->arch.mid == mid)
     105                return;
     106
     107        waking_up_mid = mid;
     108               
     109        if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) ==
     110            ESYNCH_TIMEOUT)
     111                printf("%s: waiting for processor (mid = %" PRIu32
     112                    ") timed out\n", __func__, mid);
    71113}
    72114
     
    77119        int i;
    78120       
    79         node = ofw_tree_find_child_by_device_type(ofw_tree_lookup("/"), "cpu");
    80         for (i = 0; node; node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++) {
    81                 uint32_t mid;
    82                 ofw_tree_property_t *prop;
    83                
    84                 prop = ofw_tree_getprop(node, "upa-portid");
    85                 if (!prop || !prop->value)
    86                         continue;
    87                
    88                 mid = *((uint32_t *) prop->value);
    89                 if (CPU->arch.mid == mid) {
    90                         /*
    91                          * Skip the current CPU.
    92                          */
    93                         continue;
     121        if (is_us() || is_us_iii()) {
     122                node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
     123                for (i = 0; node;
     124                     node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++)
     125                        wakeup_cpu(node);
     126        } else if (is_us_iv()) {
     127                node = ofw_tree_find_child(cpus_parent(), "cmp");
     128                while (node) {
     129                        wakeup_cpu(ofw_tree_find_child(node, "cpu@0"));
     130                        wakeup_cpu(ofw_tree_find_child(node, "cpu@1"));
     131                        node = ofw_tree_find_peer_by_name(node, "cmp");
    94132                }
    95 
    96                 /*
    97                  * Processor with ID == mid can proceed with its initialization.
    98                  */
    99                 waking_up_mid = mid;
    100                
    101                 if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT)
    102                         printf("%s: waiting for processor (mid = %" PRIu32 ") timed out\n",
    103                             __func__, mid);
    104133        }
    105134}
  • kernel/arch/sparc64/src/sparc64.c

    r0258e67 r965dc18  
    8787                 */
    8888                irq_init(1 << 11, 128);
    89                
     89
    9090                standalone_sparc64_console_init();
    9191        }
  • kernel/arch/sparc64/src/start.S

    r0258e67 r965dc18  
    2828
    2929#include <arch/arch.h>
     30#include <arch/cpu.h>
    3031#include <arch/regdef.h>
    3132#include <arch/boot/boot.h>
     
    4647
    4748#define BSP_FLAG        1
     49
     50/*
     51 * 2^PHYSMEM_ADDR_SIZE is the size of the physical address space on
     52 * a given processor.
     53 */
     54#if defined (US)
     55    #define PHYSMEM_ADDR_SIZE   41
     56#elif defined (US3)
     57    #define PHYSMEM_ADDR_SIZE   43
     58#endif
    4859
    4960/*
     
    6879        andn %o0, %l0, %l6                      ! l6 <= start of physical memory
    6980
    70         ! Get bits 40:13 of physmem_base.
     81        ! Get bits (PHYSMEM_ADDR_SIZE - 1):13 of physmem_base.
    7182        srlx %l6, 13, %l5
    72         sllx %l5, 13 + (63 - 40), %l5
    73         srlx %l5, 63 - 40, %l5                  ! l5 <= physmem_base[40:13]
     83       
     84        ! l5 <= physmem_base[(PHYSMEM_ADDR_SIZE - 1):13]
     85        sllx %l5, 13 + (63 - (PHYSMEM_ADDR_SIZE - 1)), %l5
     86        srlx %l5, 63 - (PHYSMEM_ADDR_SIZE - 1), %l5     
    7487       
    7588        /*
     
    8497        wrpr %g0, NWINDOWS - 1, %cleanwin       ! prevent needless clean_window
    8598                                                ! traps for kernel
     99                                               
     100        wrpr %g0, 0, %wstate                    ! use default spill/fill trap
    86101
    87102        wrpr %g0, 0, %tl                        ! TL = 0, primary context
     
    245260        /*
    246261         * Precompute kernel 8K TLB data template.
    247          * %l5 contains starting physical address bits [40:13]
     262         * %l5 contains starting physical address
     263         * bits [(PHYSMEM_ADDR_SIZE - 1):13]
    248264         */
    249265        sethi %hi(kernel_8k_tlb_data_template), %l4
     
    283299
    284300
     3011:
     302#ifdef CONFIG_SMP
     303        /*
     304         * Determine the width of the MID and save its mask to %g3. The width
     305         * is
     306         *      * 5 for US and US-IIIi,
     307         *      * 10 for US3 except US-IIIi.
     308         */
     309#if defined(US)
     310        mov 0x1f, %g3
     311#elif defined(US3)
     312        mov 0x3ff, %g3
     313        rdpr %ver, %g2
     314        sllx %g2, 16, %g2
     315        srlx %g2, 48, %g2
     316        cmp %g2, IMPL_ULTRASPARCIII_I
     317        move %xcc, 0x1f, %g3
     318#endif
     319
    285320        /*
    286321         * Read MID from the processor.
    287322         */
    288 1:
    289         ldxa [%g0] ASI_UPA_CONFIG, %g1
    290         srlx %g1, UPA_CONFIG_MID_SHIFT, %g1
    291         and %g1, UPA_CONFIG_MID_MASK, %g1
    292 
    293 #ifdef CONFIG_SMP
     323        ldxa [%g0] ASI_ICBUS_CONFIG, %g1
     324        srlx %g1, ICBUS_CONFIG_MID_SHIFT, %g1
     325        and %g1, %g3, %g1
     326
    294327        /*
    295328         * Active loop for APs until the BSP picks them up. A processor cannot
  • kernel/arch/sparc64/src/trap/interrupt.c

    r0258e67 r965dc18  
    6868void interrupt(int n, istate_t *istate)
    6969{
     70        uint64_t status;
    7071        uint64_t intrcv;
    7172        uint64_t data0;
     73        status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
     74        if (status & (!INTR_DISPATCH_STATUS_BUSY))
     75                panic("Interrupt Dispatch Status busy bit not set\n");
    7276
    7377        intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
    74         data0 = asi_u64_read(ASI_UDB_INTR_R, ASI_UDB_INTR_R_DATA_0);
     78#if defined (US)
     79        data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
     80#elif defined (US3)
     81        data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
     82#endif
    7583
    7684        irq_t *irq = irq_dispatch_and_lock(data0);
Note: See TracChangeset for help on using the changeset viewer.