fw-emu.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * PAL & SAL emulation.
  3.  *
  4.  * Copyright (C) 1998-2000 Hewlett-Packard Co
  5.  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  6.  *
  7.  *
  8.  * Copyright (C) 2000 Silicon Graphics, Inc.
  9.  * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com)
  10.  */
  11. #include <asm/efi.h>
  12. #include <asm/pal.h>
  13. #include <asm/sal.h>
  14. #include <asm/processor.h>
  15. #include <asm/acpi-ext.h>
  16. #include "fpmem.h"
  17. #define MB (1024*1024UL)
  18. #define GB (MB*1024UL)
  19. #define FPROM_BUG() do {while (1);} while (0)
  20. #define MAX_NODES 128
  21. #define MAX_LSAPICS 512
  22. #define MAX_CPUS 512
  23. #define MAX_CPUS_NODE 4
  24. #define CPUS_PER_NODE 4
  25. #define CPUS_PER_FSB 2
  26. #define CPUS_PER_FSB_MASK (CPUS_PER_FSB-1)
  27. #define NUM_EFI_DESCS 2
  28. typedef union ia64_nasid_va {
  29.         struct {
  30.                 unsigned long off   : 33;       /* intra-region offset */
  31. unsigned long nasid :  7; /* NASID */
  32. unsigned long off2  : 21; /* fill */
  33.                 unsigned long reg   :  3;       /* region number */
  34.         } f;
  35.         unsigned long l;
  36.         void *p;
  37. } ia64_nasid_va;
  38. typedef struct {
  39. unsigned long pc;
  40. unsigned long gp;
  41. } func_ptr_t;
  42.  
  43. #define IS_VIRTUAL_MODE()   ({struct ia64_psr psr; asm("mov %0=psr" : "=r"(psr)); psr.dt;})
  44. #define ADDR_OF(p) (IS_VIRTUAL_MODE() ? ((void*)((long)(p)+PAGE_OFFSET)) : ((void*) (p)))
  45. #define __fwtab_pa(n,x) ({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.l;})
  46. /*
  47.  * The following variables are passed thru registersfrom the configuration file and
  48.  * are set via the _start function.
  49.  */
  50. long base_nasid;
  51. long num_cpus;
  52. long bsp_entry_pc=0;
  53. long num_nodes;
  54. long app_entry_pc;
  55. int bsp_lid;
  56. func_ptr_t ap_entry;
  57. static efi_runtime_services_t    *efi_runtime_p;
  58. static char fw_mem[(  sizeof(efi_system_table_t)
  59.     + sizeof(efi_runtime_services_t)
  60.     + NUM_EFI_DESCS*sizeof(efi_config_table_t)
  61.     + sizeof(struct ia64_sal_systab)
  62.     + sizeof(struct ia64_sal_desc_entry_point)
  63.     + sizeof(struct ia64_sal_desc_ap_wakeup)
  64.     + sizeof(acpi_rsdp_t)
  65.     + sizeof(acpi_rsdt_t)
  66.     + sizeof(acpi_sapic_t)
  67.     + MAX_LSAPICS*(sizeof(acpi_entry_lsapic_t))
  68.     + (1+8*MAX_NODES)*(sizeof(efi_memory_desc_t))
  69.     + sizeof(ia64_sal_desc_ptc_t) +
  70.     + MAX_NODES*sizeof(ia64_sal_ptc_domain_info_t) +
  71.     + MAX_CPUS*sizeof(ia64_sal_ptc_domain_proc_entry_t) +
  72.     + 1024)] __attribute__ ((aligned (8)));
  73. /*
  74.  * Very ugly, but we need this in the simulator only.  Once we run on
  75.  * real hw, this can all go away.
  76.  */
  77. extern void pal_emulator_static (void);
  78. asm ("
  79. .text
  80. .proc pal_emulator_static
  81. pal_emulator_static:
  82. mov r8=-1;;
  83. cmp.eq p6,p7=6,r28;; /* PAL_PTCE_INFO */
  84. (p7) br.cond.sptk.few 1f
  85. ;;
  86. mov r8=0 /* status = 0 */
  87. movl r9=0x500000000 /* tc.base */
  88. movl r10=0x0000000200000003 /* count[0], count[1] */
  89. movl r11=0x1000000000002000 /* stride[0], stride[1] */
  90. br.cond.sptk.few rp
  91. 1: cmp.eq p6,p7=14,r28;; /* PAL_FREQ_RATIOS */
  92. (p7) br.cond.sptk.few 1f;;
  93. mov r8=0 /* status = 0 */
  94. movl r9 =0x100000064 /* proc_ratio (1/100) */
  95. movl r10=0x100000100 /* bus_ratio<<32 (1/256) */
  96. movl r11=0x10000000a /* itc_ratio<<32 (1/100) */
  97. 1: cmp.eq p6,p7=22,r28;; /* PAL_MC_DRAIN */
  98. (p7) br.cond.sptk.few 1f;;
  99. mov r8=0
  100. br.cond.sptk.few rp
  101. 1: cmp.eq p6,p7=23,r28;; /* PAL_MC_EXPECTED */
  102. (p7) br.cond.sptk.few 1f;;
  103. mov r8=0
  104. br.cond.sptk.few rp
  105. 1: br.cond.sptk.few rp
  106. .endp pal_emulator_staticn");
  107. static efi_status_t
  108. efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
  109. {
  110. if (tm) {
  111. memset(tm, 0, sizeof(*tm));
  112. tm->year = 2000;
  113. tm->month = 2;
  114. tm->day = 13;
  115. tm->hour = 10;
  116. tm->minute = 11;
  117. tm->second = 12;
  118. }
  119. if (tc) {
  120. tc->resolution = 10;
  121. tc->accuracy = 12;
  122. tc->sets_to_zero = 1;
  123. }
  124. return EFI_SUCCESS;
  125. }
  126. static void
  127. efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
  128. {
  129. while(1); /* Is there a pseudo-op to stop medusa */
  130. }
  131. static efi_status_t
  132. efi_success (void)
  133. {
  134. return EFI_SUCCESS;
  135. }
  136. static efi_status_t
  137. efi_unimplemented (void)
  138. {
  139. return EFI_UNSUPPORTED;
  140. }
  141. static long
  142. sal_emulator (long index, unsigned long in1, unsigned long in2,
  143.       unsigned long in3, unsigned long in4, unsigned long in5,
  144.       unsigned long in6, unsigned long in7)
  145. {
  146. register long r9 asm ("r9") = 0;
  147. register long r10 asm ("r10") = 0;
  148. register long r11 asm ("r11") = 0;
  149. long status;
  150. /*
  151.  * Don't do a "switch" here since that gives us code that
  152.  * isn't self-relocatable.
  153.  */
  154. status = 0;
  155. if (index == SAL_FREQ_BASE) {
  156. switch (in1) {
  157.       case SAL_FREQ_BASE_PLATFORM:
  158. r9 = 500000000;
  159. break;
  160.       case SAL_FREQ_BASE_INTERVAL_TIMER:
  161. /*
  162.  * Is this supposed to be the cr.itc frequency
  163.  * or something platform specific?  The SAL
  164.  * doc ain't exactly clear on this...
  165.  */
  166. r9 = 700000000;
  167. break;
  168.       case SAL_FREQ_BASE_REALTIME_CLOCK:
  169. r9 = 1;
  170. break;
  171.       default:
  172. status = -1;
  173. break;
  174. }
  175. } else if (index == SAL_SET_VECTORS) {
  176. if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
  177. func_ptr_t *fp;
  178. fp = ADDR_OF(&ap_entry);
  179. fp->pc = in2;
  180. fp->gp = in3;
  181. } else {
  182. status = -1;
  183. }
  184. ;
  185. } else if (index == SAL_GET_STATE_INFO) {
  186. ;
  187. } else if (index == SAL_GET_STATE_INFO_SIZE) {
  188. ;
  189. } else if (index == SAL_CLEAR_STATE_INFO) {
  190. ;
  191. } else if (index == SAL_MC_RENDEZ) {
  192. ;
  193. } else if (index == SAL_MC_SET_PARAMS) {
  194. ;
  195. } else if (index == SAL_CACHE_FLUSH) {
  196. ;
  197. } else if (index == SAL_CACHE_INIT) {
  198. ;
  199. } else if (index == SAL_UPDATE_PAL) {
  200. ;
  201. } else {
  202. status = -1;
  203. }
  204. asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
  205. return status;
  206. }
  207. /*
  208.  * This is here to work around a bug in egcs-1.1.1b that causes the
  209.  * compiler to crash (seems like a bug in the new alias analysis code.
  210.  */
  211. void *
  212. id (long addr)
  213. {
  214. return (void *) addr;
  215. }
  216. /*
  217.  * Fix the addresses in a function pointer by adding base node address
  218.  * to pc & gp.
  219.  */
  220. void
  221. fix_function_pointer(void *fp)
  222. {
  223. func_ptr_t *_fp;
  224. _fp = fp;
  225. _fp->pc = __fwtab_pa(base_nasid, _fp->pc);
  226. _fp->gp = __fwtab_pa(base_nasid, _fp->gp);
  227. }
  228. void
  229. fix_virt_function_pointer(void *fptr)
  230. {
  231.         func_ptr_t      *fp;
  232.         fp = fptr;
  233.         fp->pc = fp->pc | PAGE_OFFSET;
  234.         fp->gp = fp->gp | PAGE_OFFSET;
  235. }
  236. int
  237. efi_set_virtual_address_map(void)
  238. {
  239.         efi_runtime_services_t            *runtime;
  240.         runtime = efi_runtime_p;
  241.         fix_virt_function_pointer((void*)runtime->get_time);
  242.         fix_virt_function_pointer((void*)runtime->set_time);
  243.         fix_virt_function_pointer((void*)runtime->get_wakeup_time);
  244.         fix_virt_function_pointer((void*)runtime->set_wakeup_time);
  245.         fix_virt_function_pointer((void*)runtime->set_virtual_address_map);
  246.         fix_virt_function_pointer((void*)runtime->get_variable);
  247.         fix_virt_function_pointer((void*)runtime->get_next_variable);
  248.         fix_virt_function_pointer((void*)runtime->set_variable);
  249.         fix_virt_function_pointer((void*)runtime->get_next_high_mono_count);
  250.         fix_virt_function_pointer((void*)runtime->reset_system);
  251.         return EFI_SUCCESS;;
  252. }
  253. void
  254. sys_fw_init (const char *args, int arglen, int bsp)
  255. {
  256. /*
  257.  * Use static variables to keep from overflowing the RSE stack
  258.  */
  259. static efi_system_table_t *efi_systab;
  260. static efi_runtime_services_t *efi_runtime;
  261. static efi_config_table_t *efi_tables;
  262. static ia64_sal_desc_ptc_t *sal_ptc;
  263. static ia64_sal_ptc_domain_info_t *sal_ptcdi;
  264. static ia64_sal_ptc_domain_proc_entry_t *sal_ptclid;
  265. static acpi_rsdp_t *acpi_systab;
  266. static acpi_rsdt_t *acpi_rsdt;
  267. static acpi_sapic_t *acpi_sapic;
  268. static acpi_entry_lsapic_t *acpi_lsapic;
  269. static struct ia64_sal_systab *sal_systab;
  270. static efi_memory_desc_t *efi_memmap, *md;
  271. static unsigned long *pal_desc, *sal_desc;
  272. static struct ia64_sal_desc_entry_point *sal_ed;
  273. static struct ia64_boot_param *bp;
  274. static struct ia64_sal_desc_ap_wakeup *sal_apwake;
  275. static unsigned char checksum = 0;
  276. static char *cp, *cmd_line, *vendor;
  277. static int mdsize, domain, last_domain ;
  278. static int cnode, nasid, cpu, num_memmd, cpus_found;
  279. /*
  280.  * Pass the parameter base address to the build_efi_xxx routines.
  281.  */
  282. build_init(8LL*GB*base_nasid);
  283. num_nodes = GetNumNodes();
  284. num_cpus = GetNumCpus();
  285. memset(fw_mem, 0, sizeof(fw_mem));
  286. pal_desc = (unsigned long *) &pal_emulator_static;
  287. sal_desc = (unsigned long *) &sal_emulator;
  288. fix_function_pointer(&pal_emulator_static);
  289. fix_function_pointer(&sal_emulator);
  290. /* Align this to 16 bytes, probably EFI does this  */
  291. mdsize = (sizeof(efi_memory_desc_t) + 15) & ~15 ;
  292. cp = fw_mem;
  293. efi_systab  = (void *) cp; cp += sizeof(*efi_systab);
  294. efi_runtime_p = efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
  295. efi_tables  = (void *) cp; cp += NUM_EFI_DESCS*sizeof(*efi_tables);
  296. sal_systab  = (void *) cp; cp += sizeof(*sal_systab);
  297. sal_ed      = (void *) cp; cp += sizeof(*sal_ed);
  298. sal_ptc     = (void *) cp; cp += sizeof(*sal_ptc);
  299. sal_apwake  = (void *) cp; cp += sizeof(*sal_apwake);
  300. acpi_systab = (void *) cp; cp += sizeof(*acpi_systab);
  301. acpi_rsdt   = (void *) cp; cp += sizeof(*acpi_rsdt);
  302. acpi_sapic  = (void *) cp; cp += sizeof(*acpi_sapic);
  303. acpi_lsapic = (void *) cp; cp += num_cpus*sizeof(*acpi_lsapic);
  304. vendor      = (char *) cp; cp += 32;
  305. efi_memmap  = (void *) cp; cp += 8*32*sizeof(*efi_memmap);
  306. sal_ptcdi   = (void *) cp; cp += CPUS_PER_FSB*(1+num_nodes)*sizeof(*sal_ptcdi);
  307. sal_ptclid  = (void *) cp; cp += ((3+num_cpus)*sizeof(*sal_ptclid)+7)/8*8;
  308. cmd_line    = (void *) cp;
  309. if (args) {
  310. if (arglen >= 1024)
  311. arglen = 1023;
  312. memcpy(cmd_line, args, arglen);
  313. } else {
  314. arglen = 0;
  315. }
  316. cmd_line[arglen] = '';
  317. #ifdef BRINGUP
  318. /* for now, just bring up bash */
  319. strcpy(cmd_line, "init=/bin/bash");
  320. #else
  321. strcpy(cmd_line, "");
  322. #endif
  323. memset(efi_systab, 0, sizeof(efi_systab));
  324. efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
  325. efi_systab->hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
  326. efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
  327. efi_systab->fw_vendor = __fwtab_pa(base_nasid, vendor);
  328. efi_systab->fw_revision = 1;
  329. efi_systab->runtime = __fwtab_pa(base_nasid, efi_runtime);
  330. efi_systab->nr_tables = 2;
  331. efi_systab->tables = __fwtab_pa(base_nasid, efi_tables);
  332. memcpy(vendor, "Silicon-Graphics", 32);
  333. efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
  334. efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
  335. efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
  336. efi_runtime->get_time = __fwtab_pa(base_nasid, &efi_get_time);
  337. efi_runtime->set_time = __fwtab_pa(base_nasid, &efi_unimplemented);
  338. efi_runtime->get_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
  339. efi_runtime->set_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
  340. efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_set_virtual_address_map);
  341. efi_runtime->get_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
  342. efi_runtime->get_next_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
  343. efi_runtime->set_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
  344. efi_runtime->get_next_high_mono_count = __fwtab_pa(base_nasid, &efi_unimplemented);
  345. efi_runtime->reset_system = __fwtab_pa(base_nasid, &efi_reset_system);
  346. efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
  347. efi_tables->table = __fwtab_pa(base_nasid, sal_systab);
  348. efi_tables++;
  349. efi_tables->guid = ACPI_TABLE_GUID;
  350. efi_tables->table = __fwtab_pa(base_nasid, acpi_systab);
  351. fix_function_pointer(&efi_unimplemented);
  352. fix_function_pointer(&efi_get_time);
  353. fix_function_pointer(&efi_success);
  354. fix_function_pointer(&efi_reset_system);
  355. fix_function_pointer(&efi_set_virtual_address_map);
  356. /* fill in the ACPI system table: */
  357. memcpy(acpi_systab->signature, "RSD PTR ", 8);
  358. acpi_systab->rsdt = (struct acpi_rsdt*)__fwtab_pa(base_nasid, acpi_rsdt);
  359. memcpy(acpi_rsdt->header.signature, "RSDT",4);
  360. acpi_rsdt->header.length = sizeof(acpi_rsdt_t);
  361. memcpy(acpi_rsdt->header.oem_id, "SGI", 3);
  362. memcpy(acpi_rsdt->header.oem_table_id, "SN1", 3);
  363. acpi_rsdt->header.oem_revision = 0x00010001;
  364. acpi_rsdt->entry_ptrs[0] = __fwtab_pa(base_nasid, acpi_sapic);
  365. memcpy(acpi_sapic->header.signature, "SPIC ", 4);
  366. acpi_sapic->header.length = sizeof(acpi_sapic_t)+num_cpus*sizeof(acpi_entry_lsapic_t);
  367. for (cnode=0; cnode<num_nodes; cnode++) {
  368. nasid = GetNasid(cnode);
  369. for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
  370. if (!IsCpuPresent(cnode, cpu))
  371. continue;
  372. acpi_lsapic->type = ACPI_ENTRY_LOCAL_SAPIC;
  373. acpi_lsapic->length = sizeof(acpi_entry_lsapic_t);
  374. acpi_lsapic->acpi_processor_id = cnode*4+cpu;
  375. acpi_lsapic->flags = LSAPIC_ENABLED|LSAPIC_PRESENT;
  376. acpi_lsapic->eid = cpu;
  377. acpi_lsapic->id = nasid;
  378. acpi_lsapic++;
  379. }
  380. }
  381. /* fill in the SAL system table: */
  382. memcpy(sal_systab->signature, "SST_", 4);
  383. sal_systab->size = sizeof(*sal_systab);
  384. sal_systab->sal_rev_minor = 1;
  385. sal_systab->sal_rev_major = 0;
  386. sal_systab->entry_count = 3;
  387. strcpy(sal_systab->oem_id, "SGI");
  388. strcpy(sal_systab->product_id, "SN1");
  389. /* fill in an entry point: */
  390. sal_ed->type = SAL_DESC_ENTRY_POINT;
  391. sal_ed->pal_proc = __fwtab_pa(base_nasid, pal_desc[0]);
  392. sal_ed->sal_proc = __fwtab_pa(base_nasid, sal_desc[0]);
  393. sal_ed->gp = __fwtab_pa(base_nasid, sal_desc[1]);
  394. /* kludge the PTC domain info */
  395. sal_ptc->type = SAL_DESC_PTC;
  396. sal_ptc->num_domains = 0;
  397. sal_ptc->domain_info = __fwtab_pa(base_nasid, sal_ptcdi);
  398. cpus_found = 0;
  399. last_domain = -1;
  400. sal_ptcdi--;
  401. for (cnode=0; cnode<num_nodes; cnode++) {
  402. nasid = GetNasid(cnode);
  403. for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
  404. if (IsCpuPresent(cnode, cpu)) {
  405. domain = cnode*CPUS_PER_NODE + cpu/CPUS_PER_FSB;
  406. if (domain != last_domain) {
  407. sal_ptc->num_domains++;
  408. sal_ptcdi++;
  409. sal_ptcdi->proc_count = 0;
  410. sal_ptcdi->proc_list = __fwtab_pa(base_nasid, sal_ptclid);
  411. last_domain = domain;
  412. }
  413. sal_ptcdi->proc_count++;
  414. sal_ptclid->id = nasid;
  415. sal_ptclid->eid = cpu;
  416. sal_ptclid++;
  417. cpus_found++;
  418. }
  419. }
  420. }
  421. if (cpus_found != num_cpus)
  422. FPROM_BUG();
  423. /* Make the AP WAKEUP entry */
  424. sal_apwake->type = SAL_DESC_AP_WAKEUP;
  425. sal_apwake->mechanism = IA64_SAL_AP_EXTERNAL_INT;
  426. sal_apwake->vector = 18;
  427. for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
  428. checksum += *cp;
  429. sal_systab->checksum = -checksum;
  430. md = &efi_memmap[0];
  431. num_memmd = build_efi_memmap((void *)md, mdsize) ;
  432. bp = id(ZERO_PAGE_ADDR + (((long)base_nasid)<<33));
  433. bp->efi_systab = __fwtab_pa(base_nasid, &fw_mem);
  434. bp->efi_memmap = __fwtab_pa(base_nasid, efi_memmap);
  435. bp->efi_memmap_size = num_memmd*mdsize;
  436. bp->efi_memdesc_size = mdsize;
  437. bp->efi_memdesc_version = 0x101;
  438. bp->command_line = __fwtab_pa(base_nasid, cmd_line);
  439. bp->console_info.num_cols = 80;
  440. bp->console_info.num_rows = 25;
  441. bp->console_info.orig_x = 0;
  442. bp->console_info.orig_y = 24;
  443. bp->num_pci_vectors = 0;
  444. bp->fpswa = 0;
  445. /*
  446.  * Now pick the BSP & store it LID value in
  447.  * a global variable. Note if BSP is greater than last cpu,
  448.  * pick the last cpu.
  449.  */
  450. for (cnode=0; cnode<num_nodes; cnode++) {
  451. for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
  452. if (!IsCpuPresent(cnode, cpu))
  453. continue;
  454. bsp_lid = (GetNasid(cnode)<<24) | (cpu<<16);
  455. if (bsp-- > 0)
  456. continue;
  457. return;
  458. }
  459. }
  460. }