Resurrect amd64 support.

- Many drivers on amd64 are picking system uptime, interrupt time and ticks
  via global data structure instead of calling functions for performance
  reasons. For now just patch such address so driver will not trigger page
  fault when trying to access such data. In future, additional callout may
  be added to update data in periodic intervals.
- On amd64 we need to allocate "shadow space" on stack before calling any
  function.

Submitted by:	Paul B Mahol <onemda at gmail.com>
This commit is contained in:
Bernhard Schmidt 2010-11-22 20:46:38 +00:00
parent ea245594a6
commit 823fc080d7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215708
4 changed files with 95 additions and 8 deletions

View File

@ -311,6 +311,24 @@ windrv_unload(mod, img, len)
#define WINDRV_LOADED htonl(0x42534F44)
#ifdef __amd64__
static void
patch_user_shared_data_address(vm_offset_t img, size_t len)
{
unsigned long i, n, max_addr, *addr;
n = len - sizeof(unsigned long);
max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);
for (i = 0; i < n; i++) {
addr = (unsigned long *)(img + i);
if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {
*addr -= KI_USER_SHARED_DATA;
*addr += (unsigned long)&kuser_shared_data;
}
}
}
#endif
/*
* Loader routine for actual Windows driver modules, ultimately
* calls the driver's DriverEntry() routine.
@ -363,6 +381,10 @@ windrv_load(mod, img, len, bustype, devlist, regvals)
return (ENOEXEC);
}
#ifdef __amd64__
patch_user_shared_data_address(img, len);
#endif
/* Dynamically link USBD.SYS -- optional */
if (pe_get_import_descriptor(img, &imp_desc, "USBD") == 0) {
if (pe_patch_imports(img, "USBD", usbd_functbl))

View File

@ -605,6 +605,65 @@ struct kinterrupt {
typedef struct kinterrupt kinterrupt;
struct ksystem_time {
uint32_t low_part;
int32_t high1_time;
int32_t high2_time;
};
enum nt_product_type {
NT_PRODUCT_WIN_NT = 1,
NT_PRODUCT_LAN_MAN_NT,
NT_PRODUCT_SERVER
};
enum alt_arch_type {
STANDARD_DESIGN,
NEC98x86,
END_ALTERNATIVES
};
struct kuser_shared_data {
uint32_t tick_count;
uint32_t tick_count_multiplier;
volatile struct ksystem_time interrupt_time;
volatile struct ksystem_time system_time;
volatile struct ksystem_time time_zone_bias;
uint16_t image_number_low;
uint16_t image_number_high;
int16_t nt_system_root[260];
uint32_t max_stack_trace_depth;
uint32_t crypto_exponent;
uint32_t time_zone_id;
uint32_t large_page_min;
uint32_t reserved2[7];
enum nt_product_type nt_product_type;
uint8_t product_type_is_valid;
uint32_t nt_major_version;
uint32_t nt_minor_version;
uint8_t processor_features[64];
uint32_t reserved1;
uint32_t reserved3;
volatile uint32_t time_slip;
enum alt_arch_type alt_arch_type;
int64_t system_expiration_date;
uint32_t suite_mask;
uint8_t kdbg_enabled;
volatile uint32_t active_console;
volatile uint32_t dismount_count;
uint32_t com_plus_package;
uint32_t last_system_rit_event_tick_count;
uint32_t num_phys_pages;
uint8_t safe_boot_mode;
uint32_t trace_log;
uint64_t fill0;
uint64_t sys_call[4];
union {
volatile struct ksystem_time tick_count;
volatile uint64_t tick_count_quad;
} tick;
};
/*
* In Windows, there are Physical Device Objects (PDOs) and
* Functional Device Objects (FDOs). Physical Device Objects are
@ -1324,6 +1383,9 @@ struct drvdb_ent {
};
extern image_patch_table ntoskrnl_functbl[];
#ifdef __amd64__
extern struct kuser_shared_data kuser_shared_data;
#endif
typedef void (*funcptr)(void);
typedef int (*matchfuncptr)(interface_type, void *, void *);
@ -1438,6 +1500,7 @@ extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
* routines live in the HAL. We try to imitate this behavior.
*/
#ifdef __i386__
#define KI_USER_SHARED_DATA 0xffdf0000
#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
@ -1447,6 +1510,7 @@ extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
#endif /* __i386__ */
#ifdef __amd64__
#define KI_USER_SHARED_DATA 0xfffff78000000000UL
#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)

View File

@ -121,6 +121,7 @@ typedef struct callout_entry callout_entry;
static struct list_entry ntoskrnl_calllist;
static struct mtx ntoskrnl_calllock;
struct kuser_shared_data kuser_shared_data;
static struct list_entry ntoskrnl_intlist;
static kspin_lock ntoskrnl_intlock;

View File

@ -125,26 +125,26 @@ x86_64_wrap_end:
*/
ENTRY(x86_64_call1)
subq $8,%rsp
subq $40,%rsp
mov %rsi,%rcx
call *%rdi
addq $8,%rsp
addq $40,%rsp
ret
ENTRY(x86_64_call2)
subq $24,%rsp
subq $40,%rsp
mov %rsi,%rcx
/* %rdx is already correct */
call *%rdi
addq $24,%rsp
addq $40,%rsp
ret
ENTRY(x86_64_call3)
subq $24,%rsp
subq $40,%rsp
mov %rcx,%r8
mov %rsi,%rcx
call *%rdi
addq $24,%rsp
addq $40,%rsp
ret
ENTRY(x86_64_call4)
@ -157,13 +157,13 @@ ENTRY(x86_64_call4)
ret
ENTRY(x86_64_call5)
subq $40,%rsp
subq $48,%rsp
mov %r9,32(%rsp)
mov %r8,%r9
mov %rcx,%r8
mov %rsi,%rcx
call *%rdi
addq $40,%rsp
addq $48,%rsp
ret
ENTRY(x86_64_call6)